Commit 0b81560a090350cda281c177e1daefe742b45717

Authored by Brendan Klare
2 parents 0ecab0f9 f60a7d57

Merge turk

openbr/core/plot.cpp
@@ -219,6 +219,7 @@ bool Plot(const QStringList &files, const File &destination, bool show) @@ -219,6 +219,7 @@ bool Plot(const QStringList &files, const File &destination, bool show)
219 qDebug("Plotting %d file(s) to %s", files.size(), qPrintable(destination)); 219 qDebug("Plotting %d file(s) to %s", files.size(), qPrintable(destination));
220 220
221 const bool minimalist = destination.getBool("minimalist"); 221 const bool minimalist = destination.getBool("minimalist");
  222 + const bool uncertainty = destination.get<bool>("uncertainty");
222 223
223 // Use a br::file for simple storage of plot options 224 // Use a br::file for simple storage of plot options
224 File cmcOpts; 225 File cmcOpts;
@@ -268,7 +269,7 @@ bool Plot(const QStringList &amp;files, const File &amp;destination, bool show) @@ -268,7 +269,7 @@ bool Plot(const QStringList &amp;files, const File &amp;destination, bool show)
268 QString(" + theme(aspect.ratio=1)\n\n"))); 269 QString(" + theme(aspect.ratio=1)\n\n")));
269 270
270 p.file.write(qPrintable(QString("ggplot(CMC, aes(x=X, y=Y%1%2)) + ggtitle(\"%3\") + xlab(\"Rank\") + ylab(\"Retrieval Rate\")").arg(p.major.size > 1 ? QString(" ,colour=factor(%1)").arg(p.major.header) : QString(), p.minor.size > 1 ? QString(", linetype=factor(%1)").arg(p.minor.header) : QString(), cmcOpts.get<QString>("title",QString())) + 271 p.file.write(qPrintable(QString("ggplot(CMC, aes(x=X, y=Y%1%2)) + ggtitle(\"%3\") + xlab(\"Rank\") + ylab(\"Retrieval Rate\")").arg(p.major.size > 1 ? QString(" ,colour=factor(%1)").arg(p.major.header) : QString(), p.minor.size > 1 ? QString(", linetype=factor(%1)").arg(p.minor.header) : QString(), cmcOpts.get<QString>("title",QString())) +
271 - QString(((p.major.smooth || p.minor.smooth) ? (minimalist ? " + stat_summary(geom=\"line\", fun.y=mean, size=%1)" : " + stat_summary(geom=\"line\", fun.y=min, aes(linetype=\"Min/Max\"), size=%1) + stat_summary(geom=\"line\", " 272 + QString(((p.major.smooth || p.minor.smooth) ? (!uncertainty ? " + stat_summary(geom=\"line\", fun.y=mean, size=%1)" : " + stat_summary(geom=\"line\", fun.y=min, aes(linetype=\"Min/Max\"), size=%1) + stat_summary(geom=\"line\", "
272 "fun.y=max, aes(linetype=\"Min/Max\"), size=%1) + stat_summary(geom=\"line\", fun.y=mean, aes(linetype=\"Mean\"), size=%1) + scale_linetype_manual(\"Legend\", values=c(\"Mean\"=1, \"Min/Max\"=2))") : " + geom_line(size=%1)")).arg(QString::number(cmcOpts.get<float>("thickness",1))) + 273 "fun.y=max, aes(linetype=\"Min/Max\"), size=%1) + stat_summary(geom=\"line\", fun.y=mean, aes(linetype=\"Mean\"), size=%1) + scale_linetype_manual(\"Legend\", values=c(\"Mean\"=1, \"Min/Max\"=2))") : " + geom_line(size=%1)")).arg(QString::number(cmcOpts.get<float>("thickness",1))) +
273 (minimalist ? "" : " + scale_x_log10(labels=c(1,5,10,50,100), breaks=c(1,5,10,50,100)) + annotation_logticks(sides=\"b\")") + 274 (minimalist ? "" : " + scale_x_log10(labels=c(1,5,10,50,100), breaks=c(1,5,10,50,100)) + annotation_logticks(sides=\"b\")") +
274 (p.major.size > 1 ? getScale("colour", p.major.header, p.major.size) : QString()) + 275 (p.major.size > 1 ? getScale("colour", p.major.header, p.major.size) : QString()) +
@@ -283,7 +284,7 @@ bool Plot(const QStringList &amp;files, const File &amp;destination, bool show) @@ -283,7 +284,7 @@ bool Plot(const QStringList &amp;files, const File &amp;destination, bool show)
283 QString(", ylab=\"True Accept Rate%1\") + theme_minimal()").arg(p.minor.size > 1 ? " / " + p.minor.header : QString()) + 284 QString(", ylab=\"True Accept Rate%1\") + theme_minimal()").arg(p.minor.size > 1 ? " / " + p.minor.header : QString()) +
284 (p.major.size > 1 ? getScale("fill", p.major.header, p.major.size) : QString()) + 285 (p.major.size > 1 ? getScale("fill", p.major.header, p.major.size) : QString()) +
285 (p.minor.size > 1 ? QString(" + facet_grid(%2 ~ X)").arg(p.minor.header) : QString(" + facet_grid(. ~ X, labeller=far_labeller)")) + 286 (p.minor.size > 1 ? QString(" + facet_grid(%2 ~ X)").arg(p.minor.header) : QString(" + facet_grid(. ~ X, labeller=far_labeller)")) +
286 - QString(" + scale_y_continuous(labels=percent) + theme(legend.position=\"none\", axis.text.x=element_text(angle=-90, hjust=0))%1").arg((p.major.smooth || p.minor.smooth) ? "" : " + geom_text(data=BC, aes(label=Y, y=0.05))\n\n"))); 287 + QString(" + scale_y_continuous(labels=percent) + theme(legend.position=\"none\", axis.text.x=element_text(angle=-90, hjust=0))%1").arg((p.major.smooth || p.minor.smooth) ? "" : " + geom_text(data=BC, aes(label=Y, y=0.05))") + "\n\n"));
287 288
288 p.file.write(qPrintable(QString("qplot(X, Y, data=ERR%1, linetype=Error").arg((p.major.smooth || p.minor.smooth) ? ", geom=\"smooth\", method=loess, level=0.99" : ", geom=\"line\"") + 289 p.file.write(qPrintable(QString("qplot(X, Y, data=ERR%1, linetype=Error").arg((p.major.smooth || p.minor.smooth) ? ", geom=\"smooth\", method=loess, level=0.99" : ", geom=\"line\"") +
289 ((p.flip ? p.major.size : p.minor.size) > 1 ? QString(", colour=factor(%1)").arg(p.flip ? p.major.header : p.minor.header) : QString()) + 290 ((p.flip ? p.major.size : p.minor.size) > 1 ? QString(", colour=factor(%1)").arg(p.flip ? p.major.header : p.minor.header) : QString()) +
openbr/plugins/misc.cpp
@@ -366,6 +366,29 @@ BR_REGISTER(Transform, RegexPropertyTransform) @@ -366,6 +366,29 @@ BR_REGISTER(Transform, RegexPropertyTransform)
366 366
367 /*! 367 /*!
368 * \ingroup transforms 368 * \ingroup transforms
  369 + * \brief Create matrix from metadata values.
  370 + * \author Josh Klontz \cite jklontz
  371 + */
  372 +class ExtractMetadataTransform : public UntrainableMetaTransform
  373 +{
  374 + Q_OBJECT
  375 + Q_PROPERTY(QStringList keys READ get_keys WRITE set_keys RESET reset_keys STORED false)
  376 + BR_PROPERTY(QStringList, keys, QStringList())
  377 +
  378 + void project(const Template &src, Template &dst) const
  379 + {
  380 + dst.file = src.file;
  381 + QList<float> values;
  382 + foreach (const QString &key, keys)
  383 + values.append(src.file.get<float>(key));
  384 + dst.append(OpenCVUtils::toMat(values, 1));
  385 + }
  386 +};
  387 +
  388 +BR_REGISTER(Transform, ExtractMetadataTransform)
  389 +
  390 +/*!
  391 + * \ingroup transforms
369 * \brief Store the last matrix of the input template as a metadata key with input property name. 392 * \brief Store the last matrix of the input template as a metadata key with input property name.
370 * \author Charles Otto \cite caotto 393 * \author Charles Otto \cite caotto
371 */ 394 */
openbr/plugins/output.cpp
@@ -365,15 +365,22 @@ BR_REGISTER(Output, EmptyOutput) @@ -365,15 +365,22 @@ BR_REGISTER(Output, EmptyOutput)
365 class evalOutput : public MatrixOutput 365 class evalOutput : public MatrixOutput
366 { 366 {
367 Q_OBJECT 367 Q_OBJECT
  368 + Q_PROPERTY(QString target READ get_target WRITE set_target RESET reset_target STORED false)
  369 + Q_PROPERTY(QString query READ get_query WRITE set_query RESET reset_query STORED false)
368 Q_PROPERTY(bool crossValidate READ get_crossValidate WRITE set_crossValidate RESET reset_crossValidate STORED false) 370 Q_PROPERTY(bool crossValidate READ get_crossValidate WRITE set_crossValidate RESET reset_crossValidate STORED false)
369 BR_PROPERTY(bool, crossValidate, true) 371 BR_PROPERTY(bool, crossValidate, true)
  372 + BR_PROPERTY(QString, target, QString())
  373 + BR_PROPERTY(QString, query, QString())
370 374
371 ~evalOutput() 375 ~evalOutput()
372 { 376 {
  377 + if (!target.isEmpty()) targetFiles = TemplateList::fromGallery(target).files();
  378 + if (!query.isEmpty()) queryFiles = TemplateList::fromGallery(query).files();
  379 +
373 if (data.data) { 380 if (data.data) {
374 const QString csv = QString(file.name).replace(".eval", ".csv"); 381 const QString csv = QString(file.name).replace(".eval", ".csv");
375 if ((Globals->crossValidate == 0) || (!crossValidate)) { 382 if ((Globals->crossValidate == 0) || (!crossValidate)) {
376 - Evaluate(data,targetFiles, queryFiles, csv); 383 + Evaluate(data, targetFiles, queryFiles, csv);
377 } else { 384 } else {
378 QFutureSynchronizer<float> futures; 385 QFutureSynchronizer<float> futures;
379 for (int i=0; i<Globals->crossValidate; i++) 386 for (int i=0; i<Globals->crossValidate; i++)
openbr/plugins/turk.cpp
@@ -13,10 +13,6 @@ namespace br @@ -13,10 +13,6 @@ namespace br
13 class turkGallery : public Gallery 13 class turkGallery : public Gallery
14 { 14 {
15 Q_OBJECT 15 Q_OBJECT
16 - Q_PROPERTY(bool flat READ get_flat WRITE set_flat RESET reset_flat STORED false)  
17 - Q_PROPERTY(bool normalize READ get_normalize WRITE set_normalize RESET reset_normalize STORED false)  
18 - BR_PROPERTY(bool, flat, false)  
19 - BR_PROPERTY(bool, normalize, false)  
20 16
21 struct Attribute : public QStringList 17 struct Attribute : public QStringList
22 { 18 {
@@ -40,7 +36,8 @@ class turkGallery : public Gallery @@ -40,7 +36,8 @@ class turkGallery : public Gallery
40 } 36 }
41 37
42 Attribute normal(name); 38 Attribute normal(name);
43 - const float sum = Common::Sum(values); 39 + float sum = Common::Sum(values);
  40 + if (sum == 0) sum = 1;
44 for (int i=0; i<values.size(); i++) 41 for (int i=0; i<values.size(); i++)
45 normal.append(QString::number(values[i] / sum)); 42 normal.append(QString::number(values[i] / sum));
46 return normal; 43 return normal;
@@ -50,38 +47,28 @@ class turkGallery : public Gallery @@ -50,38 +47,28 @@ class turkGallery : public Gallery
50 TemplateList readBlock(bool *done) 47 TemplateList readBlock(bool *done)
51 { 48 {
52 *done = true; 49 *done = true;
53 - TemplateList templates;  
54 QStringList lines = QtUtils::readLines(file); 50 QStringList lines = QtUtils::readLines(file);
55 - if (lines.empty())  
56 - qFatal(".turk Gallery missing header.");  
57 - QList<Attribute> types;  
58 - foreach (const QString &header, parse(lines.takeFirst()))  
59 - types.append(header); 51 + QList<Attribute> headers;
  52 + if (!lines.isEmpty())
  53 + foreach (const QString &header, parse(lines.takeFirst()))
  54 + headers.append(header);
60 55
  56 + TemplateList templates;
61 foreach (const QString &line, lines) { 57 foreach (const QString &line, lines) {
62 - const QStringList words = parse(line);  
63 - if (words.size() != types.size())  
64 - qFatal(".turk Gallery incorrect column count.");  
65 -  
66 - File f(words[0], words[0].mid(0,5));  
67 - for (int i=1; i<words.size(); i++) {  
68 - Attribute &type = types[i];  
69 - Attribute rating(words[i]);  
70 - if (type.size() != rating.size())  
71 - qFatal(".turk Gallery incorrect ratings count."); 58 + QStringList words = parse(line);
  59 + if (words.size() != headers.size())
  60 + qFatal("turkGallery invalid column count");
72 61
73 - if (normalize)  
74 - rating = rating.normalized(); 62 + File f;
  63 + f.name = words[0];
  64 + f.set("Label", words[0].mid(0,5));
75 65
76 - if (flat) {  
77 - for (int j=0; j<type.size(); j++)  
78 - f.set(type.name + "_" + type[j], rating[j]);  
79 - } else {  
80 - QMap<QString,QVariant> categoryMap;  
81 - for (int j=0; j<type.size(); j++)  
82 - categoryMap.insert(type[j], rating[j]);  
83 - f.set(type.name, categoryMap);  
84 - } 66 + for (int i=1; i<words.size(); i++) {
  67 + Attribute ratings = Attribute(words[i]).normalized();
  68 + if (headers[i].size() != ratings.size())
  69 + qFatal("turkGallery invalid attribute count");
  70 + for (int j=0; j<ratings.size(); j++)
  71 + f.set(headers[i].name + "_" + headers[i][j], ratings[j]);
85 } 72 }
86 templates.append(f); 73 templates.append(f);
87 } 74 }
@@ -97,58 +84,6 @@ class turkGallery : public Gallery @@ -97,58 +84,6 @@ class turkGallery : public Gallery
97 84
98 BR_REGISTER(Gallery, turkGallery) 85 BR_REGISTER(Gallery, turkGallery)
99 86
100 -static Template unmap(const Template &t, const QString& variable, const float maxVotes, const float maxRange, const float minRange, const bool classify, const bool consensusOnly) {  
101 - // Create a new template matching the one containing the votes in the map structure  
102 - // but remove the map structure  
103 - Template expandedT = t;  
104 - expandedT.file.remove(variable);  
105 -  
106 - QMap<QString,QVariant> map = t.file.get<QMap<QString,QVariant> >(variable);  
107 - QMapIterator<QString, QVariant> i(map);  
108 - bool ok;  
109 -  
110 - while (i.hasNext()) {  
111 - i.next();  
112 - // Normalize to [minRange,maxRange]  
113 - float value = i.value().toFloat(&ok)*(maxRange-minRange)/maxVotes - minRange;  
114 - if (!ok) qFatal("Failed to expand Turk votes for %s", qPrintable(variable));  
115 - if (classify) (value > maxRange-((maxRange-minRange)/2)) ? value = maxRange : value = minRange;  
116 - else if (consensusOnly && (value != maxRange && value != minRange)) continue;  
117 - expandedT.file.set(i.key(),value);  
118 - }  
119 -  
120 - return expandedT;  
121 -}  
122 -  
123 -/*!  
124 - * \ingroup transforms  
125 - * \brief Converts Amazon MTurk labels to a non-map format for use in a transform  
126 - * \author Scott Klum \cite sklum  
127 - */  
128 -class TurkTransform : public UntrainableTransform  
129 -{  
130 - Q_OBJECT  
131 - Q_PROPERTY(QString HIT READ get_HIT WRITE set_HIT RESET reset_HIT STORED false)  
132 - Q_PROPERTY(float maxVotes READ get_maxVotes WRITE set_maxVotes RESET reset_maxVotes STORED false)  
133 - Q_PROPERTY(float maxRange READ get_maxRange WRITE set_maxRange RESET reset_maxRange STORED false)  
134 - Q_PROPERTY(float minRange READ get_minRange WRITE set_minRange RESET reset_minRange STORED false)  
135 - Q_PROPERTY(bool classify READ get_classify WRITE set_classify RESET reset_classify STORED false)  
136 - Q_PROPERTY(bool consensusOnly READ get_consensusOnly WRITE set_consensusOnly RESET reset_consensusOnly STORED false)  
137 - BR_PROPERTY(QString, HIT, QString())  
138 - BR_PROPERTY(float, maxVotes, 1)  
139 - BR_PROPERTY(float, maxRange, 1)  
140 - BR_PROPERTY(float, minRange, 0)  
141 - BR_PROPERTY(bool, classify, false)  
142 - BR_PROPERTY(bool, consensusOnly, false)  
143 -  
144 - void project(const Template &src, Template &dst) const  
145 - {  
146 - dst = unmap(src, HIT, maxVotes, maxRange, minRange, classify, consensusOnly);  
147 - }  
148 -};  
149 -  
150 -BR_REGISTER(Transform, TurkTransform)  
151 -  
152 /*! 87 /*!
153 * \ingroup transforms 88 * \ingroup transforms
154 * \brief Convenience class for training turk attribute regressors 89 * \brief Convenience class for training turk attribute regressors
@@ -159,27 +94,21 @@ class TurkClassifierTransform : public Transform @@ -159,27 +94,21 @@ class TurkClassifierTransform : public Transform
159 Q_OBJECT 94 Q_OBJECT
160 Q_PROPERTY(QString key READ get_key WRITE set_key RESET reset_key STORED false) 95 Q_PROPERTY(QString key READ get_key WRITE set_key RESET reset_key STORED false)
161 Q_PROPERTY(QStringList values READ get_values WRITE set_values RESET reset_values STORED false) 96 Q_PROPERTY(QStringList values READ get_values WRITE set_values RESET reset_values STORED false)
162 - Q_PROPERTY(float maxVotes READ get_maxVotes WRITE set_maxVotes RESET reset_maxVotes STORED false)  
163 Q_PROPERTY(bool isMeta READ get_isMeta WRITE set_isMeta RESET reset_isMeta STORED false) 97 Q_PROPERTY(bool isMeta READ get_isMeta WRITE set_isMeta RESET reset_isMeta STORED false)
164 BR_PROPERTY(QString, key, QString()) 98 BR_PROPERTY(QString, key, QString())
165 BR_PROPERTY(QStringList, values, QStringList()) 99 BR_PROPERTY(QStringList, values, QStringList())
166 - BR_PROPERTY(float, maxVotes, 1)  
167 BR_PROPERTY(bool, isMeta, false) 100 BR_PROPERTY(bool, isMeta, false)
168 101
169 Transform *child; 102 Transform *child;
170 103
171 void init() 104 void init()
172 { 105 {
173 - QString algorithm = QString("Turk(%1, %2)+").arg(key, QString::number(maxVotes));  
174 QStringList classifiers; 106 QStringList classifiers;
175 foreach (const QString &value, values) 107 foreach (const QString &value, values)
176 - classifiers.append(QString("SVM(RBF,EPS_SVR,returnDFVal=true,inputVariable=%1,outputVariable=predicted_%1)").arg(value));  
177 - algorithm += classifiers.join("/");  
178 - if (values.size() > 1)  
179 - algorithm += "+Cat"; 108 + classifiers.append(QString("SVM(RBF,EPS_SVR,returnDFVal=true,inputVariable=%1,outputVariable=predicted_%1)").arg(key + "_" + value));
  109 + child = Transform::make(classifiers.join("/") + (classifiers.size() > 1 ? "+Cat" : ""));
180 if (isMeta) 110 if (isMeta)
181 algorithm += QsString("+Average+SaveMat(predicted_%1)").arg(value); 111 algorithm += QsString("+Average+SaveMat(predicted_%1)").arg(value);
182 - child = Transform::make(algorithm);  
183 } 112 }
184 113
185 void train(const QList<TemplateList> &data) 114 void train(const QList<TemplateList> &data)
@@ -206,44 +135,6 @@ class TurkClassifierTransform : public Transform @@ -206,44 +135,6 @@ class TurkClassifierTransform : public Transform
206 BR_REGISTER(Transform, TurkClassifierTransform) 135 BR_REGISTER(Transform, TurkClassifierTransform)
207 136
208 /*! 137 /*!
209 - * \ingroup transforms  
210 - * \brief Converts metadata into a map structure  
211 - * \author Scott Klum \cite sklum  
212 - */  
213 -class MapTransform : public UntrainableTransform  
214 -{  
215 - Q_OBJECT  
216 - Q_PROPERTY(QStringList inputVariables READ get_inputVariables WRITE set_inputVariables RESET reset_inputVariables STORED false)  
217 - Q_PROPERTY(QString outputVariable READ get_outputVariable WRITE set_outputVariable RESET reset_outputVariable STORED false)  
218 - BR_PROPERTY(QStringList, inputVariables, QStringList())  
219 - BR_PROPERTY(QString, outputVariable, QString())  
220 -  
221 - void project(const Template &src, Template &dst) const  
222 - {  
223 - dst = map(src);  
224 - }  
225 -  
226 - Template map(const Template &t) const {  
227 - Template mappedT = t;  
228 - QMap<QString,QVariant> map;  
229 -  
230 - foreach(const QString &s, inputVariables) {  
231 - if (t.file.contains(s)) {  
232 - map.insert(s,t.file.value(s));  
233 - mappedT.file.remove(s);  
234 - }  
235 - }  
236 -  
237 - if (!map.isEmpty()) mappedT.file.set(outputVariable,map);  
238 -  
239 - return mappedT;  
240 - }  
241 -};  
242 -  
243 -BR_REGISTER(Transform, MapTransform)  
244 -  
245 -  
246 -/*!  
247 * \ingroup distances 138 * \ingroup distances
248 * \brief Unmaps Turk HITs to be compared against query mats 139 * \brief Unmaps Turk HITs to be compared against query mats
249 * \author Scott Klum \cite sklum 140 * \author Scott Klum \cite sklum
@@ -251,33 +142,17 @@ BR_REGISTER(Transform, MapTransform) @@ -251,33 +142,17 @@ BR_REGISTER(Transform, MapTransform)
251 class TurkDistance : public Distance 142 class TurkDistance : public Distance
252 { 143 {
253 Q_OBJECT 144 Q_OBJECT
254 - Q_PROPERTY(QString HIT READ get_HIT WRITE set_HIT RESET reset_HIT)  
255 - Q_PROPERTY(QStringList keys READ get_keys WRITE set_keys RESET reset_keys STORED false)  
256 - Q_PROPERTY(float maxVotes READ get_maxVotes WRITE set_maxVotes RESET reset_maxVotes STORED false)  
257 - Q_PROPERTY(float maxRange READ get_maxRange WRITE set_maxRange RESET reset_maxRange STORED false)  
258 - Q_PROPERTY(float minRange READ get_minRange WRITE set_minRange RESET reset_minRange STORED false)  
259 - Q_PROPERTY(bool classify READ get_classify WRITE set_classify RESET reset_classify STORED false)  
260 - Q_PROPERTY(bool consensusOnly READ get_consensusOnly WRITE set_consensusOnly RESET reset_consensusOnly STORED false)  
261 - BR_PROPERTY(QString, HIT, QString())  
262 - BR_PROPERTY(QStringList, keys, QStringList())  
263 - BR_PROPERTY(float, maxVotes, 1)  
264 - BR_PROPERTY(float, maxRange, 1)  
265 - BR_PROPERTY(float, minRange, 0)  
266 - BR_PROPERTY(bool, classify, false)  
267 - BR_PROPERTY(bool, consensusOnly, false) 145 + Q_PROPERTY(QString key READ get_key WRITE set_key RESET reset_key)
  146 + Q_PROPERTY(QStringList values READ get_values WRITE set_values RESET reset_values STORED false)
  147 + BR_PROPERTY(QString, key, QString())
  148 + BR_PROPERTY(QStringList, values, QStringList())
268 149
269 float compare(const Template &target, const Template &query) const 150 float compare(const Template &target, const Template &query) const
270 { 151 {
271 - Template t = unmap(target, HIT, maxVotes, maxRange, minRange, classify, consensusOnly);  
272 -  
273 - QList<float> targetValues;  
274 - foreach(const QString &s, keys) targetValues.append(t.file.get<float>(s));  
275 -  
276 - float stddev = .75;  
277 - 152 + const float stddev = .75;
278 float score = 0; 153 float score = 0;
279 - for (int i=0; i<targetValues.size(); i++) score += 1/(stddev*sqrt(2*CV_PI))*exp(-0.5*pow((query.m().at<float>(0,i)-targetValues[i])/stddev, 2));  
280 - 154 + for (int i=0; i<values.size(); i++)
  155 + score += 1 / (stddev*sqrt(2*CV_PI)) * exp(-0.5*pow((query.m().at<float>(0,i)-target.file.get<float>(key + "_" + values[i]))/stddev, 2));
281 return score; 156 return score;
282 } 157 }
283 }; 158 };