Commit 9628df78862a9fdd42be68e382c8a745ec77d903

Authored by sklum
1 parent 6553e4ab

Complicated turk processing

openbr/plugins/distance.cpp
... ... @@ -21,6 +21,7 @@
21 21 #include <opencv2/imgproc/imgproc_c.h>
22 22 #include "openbr_internal.h"
23 23  
  24 +#include "openbr/core/common.h"
24 25 #include "openbr/core/distance_sse.h"
25 26 #include "openbr/core/qtutils.h"
26 27 #include "openbr/core/opencvutils.h"
... ... @@ -391,31 +392,74 @@ BR_REGISTER(Distance, OnlineDistance)
391 392  
392 393 /*!
393 394 * \ingroup distances
394   - * \brief Attenuation function based distance from attributes
  395 + * \brief Unmaps turk votes to be used in a distance
395 396 * \author Scott Klum \cite sklum
396 397 */
397   -class AttributeDistance : public Distance
  398 +class TurkDistance : public Distance
398 399 {
399 400 Q_OBJECT
400   - Q_PROPERTY(QString targetAttribute READ get_targetAttribute WRITE set_targetAttribute RESET reset_targetAttribute STORED false)
401   - Q_PROPERTY(QString queryAttribute READ get_queryAttribute WRITE set_queryAttribute RESET reset_queryAttribute STORED false)
402   - BR_PROPERTY(QString, targetAttribute, QString())
403   - BR_PROPERTY(QString, queryAttribute, QString())
404   -
  401 + Q_PROPERTY(br::Distance* distance READ get_distance WRITE set_distance RESET reset_distance)
  402 + Q_PROPERTY(QString category READ get_category WRITE set_category RESET reset_category)
  403 + Q_PROPERTY(QStringList targetAttributes READ get_targetAttributes WRITE set_targetAttributes RESET reset_targetAttributes STORED false)
  404 + Q_PROPERTY(QStringList queryAttributes READ get_queryAttributes WRITE set_queryAttributes RESET reset_queryAttributes STORED false)
  405 + BR_PROPERTY(br::Distance*, distance, NULL)
  406 + BR_PROPERTY(QString, category, QString())
  407 + BR_PROPERTY(QStringList, targetAttributes, QStringList())
  408 + BR_PROPERTY(QStringList, queryAttributes, QStringList())
  409 +;
405 410 float compare(const Template &target, const Template &query) const
406 411 {
407   - float queryValue = query.file.get<float>(queryAttribute);
408   - float targetValue = target.file.get<float>(targetAttribute);
  412 + Template t = unmap(target,category);
  413 + Template q = unmap(query,category);
  414 +
  415 + QList<float> targetValues, queryValues;
  416 + foreach(const QString &s, targetAttributes) targetValues.append(t.file.get<float>(s));
  417 + foreach(const QString &s, queryAttributes) queryValues.append(q.file.get<float>(s));
409 418  
410   - // TODO: Set this magic number to something meaningful
411   - float stddev = .5;
  419 + float stddev = .75;
  420 + float score = 0;
  421 + for(int i=0; i<targetValues.size(); i++) score += 1./(stddev*sqrt(2*CV_PI))*exp(-0.5*pow((queryValues[i]-targetValues[i])/stddev, 2));
412 422  
413   - if (queryValue == targetValue) return 1;
414   - else return 1/(stddev*sqrt(2*CV_PI))*exp(-0.5*pow((targetValue-queryValue)/stddev, 2));
  423 + return score;
  424 + }
  425 +
  426 + Template unmap(const Template &t, const QString& variable) const {
  427 + // Create a new template matching the one containing the votes in the map structure
  428 + // but remove the map structure
  429 + Template expandedT = t;
  430 + expandedT.file.remove(variable);
  431 +
  432 + QMap<QString,QVariant> map = t.file.get<QMap<QString,QVariant> >(variable);
  433 + QMapIterator<QString, QVariant> i(map);
  434 +
  435 + while (i.hasNext()) {
  436 + i.next();
  437 + float value = i.value().toFloat();
  438 + expandedT.file.set(i.key(),value);
  439 + }
  440 +
  441 + return expandedT;
415 442 }
416 443 };
417 444  
418   -BR_REGISTER(Distance, AttributeDistance)
  445 +BR_REGISTER(Distance, TurkDistance)
  446 +
  447 +/*!
  448 + * \ingroup distances
  449 + * \brief Attenuation function based distance
  450 + * \author Scott Klum \cite sklum
  451 + */
  452 +class AttenuationDistance : public Distance
  453 +{
  454 + Q_OBJECT
  455 +;
  456 + float compare(const Template &target, const Template &query) const
  457 + {
  458 + return 1;
  459 + }
  460 +};
  461 +
  462 +BR_REGISTER(Distance, AttenuationDistance)
419 463  
420 464 /*!
421 465 * \ingroup distances
... ... @@ -435,18 +479,18 @@ class SumDistance : public Distance
435 479 futures.addFuture(QtConcurrent::run(distance, &Distance::train, data));
436 480 futures.waitForFinished();
437 481 }
438   -;
  482 +
439 483 float compare(const Template &target, const Template &query) const
440 484 {
441 485 float result = 0;
442 486  
443   - QList<float> scores;
444 487 foreach (br::Distance *distance, distances) {
445   - scores.append(distance->compare(target, query));
446   - result += distance->compare(target, query);
  488 + float score = distance->compare(target, query);
447 489  
448   - if (result == -std::numeric_limits<float>::max())
  490 + if (score == -std::numeric_limits<float>::max())
449 491 return result;
  492 +
  493 + result += score;
450 494 }
451 495  
452 496 return result;
... ...
openbr/plugins/template.cpp
... ... @@ -95,42 +95,76 @@ BR_REGISTER(Transform, SelectPointsTransform)
95 95  
96 96 /*!
97 97 * \ingroup transforms
98   - * \brief Converts Amazon MTurk labels
  98 + * \brief Converts Amazon MTurk labels to a non-map format for use in a transform
  99 + * Also optionally normalizes and/or classifies the votes
99 100 * \author Scott Klum \cite sklum
100 101 */
101   -class MTurkTransform : public UntrainableTransform
  102 +/*
  103 +class TurkTransform : public Transform
102 104 {
103 105 Q_OBJECT
104 106 Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)
  107 + Q_PROPERTY(QString outputVariable READ get_outputVariable WRITE set_outputVariable RESET reset_outputVariable STORED false)
105 108 Q_PROPERTY(float maxVotes READ get_maxVotes WRITE set_maxVotes RESET reset_maxVotes STORED false)
  109 + Q_PROPERTY(br::Transform* transform READ get_transform WRITE set_transform RESET reset_transform STORED true)
106 110 Q_PROPERTY(bool classify READ get_classify WRITE set_classify RESET reset_classify STORED false)
107 111 Q_PROPERTY(bool consensusOnly READ get_consensusOnly WRITE set_consensusOnly RESET reset_consensusOnly STORED false)
108 112 BR_PROPERTY(QString, inputVariable, QString())
  113 + BR_PROPERTY(QString, outputVariable, QString())
109 114 BR_PROPERTY(float, maxVotes, 1.)
  115 + BR_PROPERTY(br::Transform*, transform, NULL)
110 116 BR_PROPERTY(bool, classify, false)
111 117 BR_PROPERTY(bool, consensusOnly, false)
112 118  
  119 + void train(const TemplateList &data)
  120 + {
  121 + TemplateList expandedData;
  122 +
  123 + foreach(const Template &t, data)
  124 + expandedData.append(expandVotes(t));
  125 +
  126 + transform->train(expandedData);
  127 + }
  128 +
113 129 void project(const Template &src, Template &dst) const
114 130 {
  131 + // Unmap, project, remap
  132 + transform->project(expandVotes(src),dst);
  133 +
  134 + QMap<QString,QVariant> map = src.file.get<QMap<QString,QVariant> >(inputVariable);
  135 + // We expect that whatever transform does to the inputVariable,
  136 + // the outputVariable will be in the form of (or convertible to) a float
  137 + map.insert(outputVariable,dst.file.get<float>(outputVariable));
  138 +
115 139 dst = src;
  140 + dst.file.set(inputVariable,map);
  141 + }
116 142  
117   - QMap<QString,QVariant> map = dst.file.get<QMap<QString,QVariant> >(inputVariable);
  143 + Template expandVotes(const Template &t) const {
  144 + // Create a new template matching the one containing the votes in the map structure
  145 + // but remove the map structure
  146 + Template expandedT = t;
  147 + expandedT.file.remove(inputVariable);
118 148  
  149 + QMap<QString,QVariant> map = t.file.get<QMap<QString,QVariant> >(inputVariable);
  150 + QMapIterator<QString, QVariant> i(map);
119 151 bool ok;
120 152  
121   - QMapIterator<QString, QVariant> i(map);
122 153 while (i.hasNext()) {
123 154 i.next();
124 155 // Normalize to [-1,1]
125 156 float value = i.value().toFloat(&ok)/maxVotes;//* 2./maxVotes - 1;
  157 + if (!ok) qFatal("Failed to expand Turk votes for %s", inputVariable);
126 158 if (classify) (value > 0) ? value = 1 : value = -1;
127 159 else if (consensusOnly && (value != 1 && value != -1)) continue;
128   - dst.file.set(i.key(),value);
  160 + expandedT.file.set(i.key(),value);
129 161 }
  162 +
  163 + return expandedT;
130 164 }
131 165 };
132 166  
133   -BR_REGISTER(Transform, MTurkTransform)
  167 +BR_REGISTER(Transform, TurkTransform)*/
134 168  
135 169 } // namespace br
136 170  
... ...
openbr/plugins/turk.cpp 0 → 100644
  1 +#include "openbr_internal.h"
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup transforms
  8 + * \brief Converts Amazon MTurk labels to a non-map format for use in a transform
  9 + * Also optionally normalizes and/or classifies the votes
  10 + * \author Scott Klum \cite sklum
  11 + */
  12 +class TurkTransform : public UntrainableTransform
  13 +{
  14 + Q_OBJECT
  15 + Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)
  16 + Q_PROPERTY(float maxVotes READ get_maxVotes WRITE set_maxVotes RESET reset_maxVotes STORED false)
  17 + Q_PROPERTY(bool classify READ get_classify WRITE set_classify RESET reset_classify STORED false)
  18 + Q_PROPERTY(bool consensusOnly READ get_consensusOnly WRITE set_consensusOnly RESET reset_consensusOnly STORED false)
  19 + BR_PROPERTY(QString, inputVariable, QString())
  20 + BR_PROPERTY(float, maxVotes, 1.)
  21 + BR_PROPERTY(bool, classify, false)
  22 + BR_PROPERTY(bool, consensusOnly, false)
  23 +
  24 + void project(const Template &src, Template &dst) const
  25 + {
  26 + dst = unmap(src);
  27 + }
  28 +
  29 + Template unmap(const Template &t) const {
  30 + // Create a new template matching the one containing the votes in the map structure
  31 + // but remove the map structure
  32 + Template expandedT = t;
  33 + expandedT.file.remove(inputVariable);
  34 +
  35 + QMap<QString,QVariant> map = t.file.get<QMap<QString,QVariant> >(inputVariable);
  36 + QMapIterator<QString, QVariant> i(map);
  37 + bool ok;
  38 +
  39 + while (i.hasNext()) {
  40 + i.next();
  41 + // Normalize to [-1,1]
  42 + float value = i.value().toFloat(&ok)/maxVotes;//* 2./maxVotes - 1;
  43 + if (!ok) qFatal("Failed to expand Turk votes for %s", inputVariable);
  44 + if (classify) (value > 0) ? value = 1 : value = -1;
  45 + else if (consensusOnly && (value != 1 && value != -1)) continue;
  46 + expandedT.file.set(i.key(),value);
  47 + }
  48 +
  49 + return expandedT;
  50 + }
  51 +};
  52 +
  53 +BR_REGISTER(Transform, TurkTransform)
  54 +
  55 +/*!
  56 + * \ingroup transforms
  57 + * \brief Converts metadata into a map structure
  58 + * \author Scott Klum \cite sklum
  59 + */
  60 +class MapTransform : public UntrainableTransform
  61 +{
  62 + Q_OBJECT
  63 + Q_PROPERTY(QStringList inputVariables READ get_inputVariables WRITE set_inputVariables RESET reset_inputVariables STORED false)
  64 + Q_PROPERTY(QString outputVariable READ get_outputVariable WRITE set_outputVariable RESET reset_outputVariable STORED false)
  65 + BR_PROPERTY(QStringList, inputVariables, QStringList())
  66 + BR_PROPERTY(QString, outputVariable, QString())
  67 +
  68 + void project(const Template &src, Template &dst) const
  69 + {
  70 + dst = map(src);
  71 + }
  72 +
  73 + Template map(const Template &t) const {
  74 + Template mappedT = t;
  75 + QMap<QString,QVariant> map;
  76 +
  77 + foreach(const QString &s, inputVariables) {
  78 + // Get checks if the variant stored in m_metdata can be
  79 + // converted to the type T. For some reason, you cannot
  80 + // convert from a QVariant to a QVariant. Thus, this transform
  81 + // has to assume that the metadata we want to organize can be
  82 + // converted to a float, resulting in a loss of generality :(.
  83 + if (t.file.contains(s)) {
  84 + map.insert(s,t.file.get<float>(s));
  85 + mappedT.file.remove(s);
  86 + }
  87 + }
  88 +
  89 + if (!map.isEmpty()) mappedT.file.set(outputVariable,map);
  90 +
  91 + return mappedT;
  92 + }
  93 +};
  94 +
  95 +BR_REGISTER(Transform, MapTransform)
  96 +
  97 +} // namespace br
  98 +
  99 +#include "turk.moc"
... ...