Commit 6cbb46129183130e6987081f2bca873033836eeb

Authored by jklontz
2 parents e2fb91d8 b9e7e4b2

Merge pull request #24 from biometrics/file_refactoring

File refactoring
CHANGELOG.md
... ... @@ -4,7 +4,8 @@
4 4 * Enrolling files/folders are now sorted naturally instead of alpha numerically
5 5 * YouTubeFacesDBTransform implements Dr. Wolf's experimental protocol
6 6 * NEC3 refactored
7   -* Updated transform API to add support for time-varying transforms
  7 +* Updated transform API to add support for time-varying transforms per issue (#23)
  8 +* Refactored File class to improve point and rect storage (#22)
8 9  
9 10 0.2.0 - 2/23/13
10 11 ===============
... ...
app/examples/age_estimation.cpp
... ... @@ -31,7 +31,7 @@ static void printTemplate(const br::Template &t)
31 31 {
32 32 printf("%s age: %d\n",
33 33 qPrintable(t.file.fileName()),
34   - t.file.getInt("Label"));
  34 + t.file.get<int>("Label"));
35 35 }
36 36  
37 37 int main(int argc, char *argv[])
... ...
app/examples/face_recognition.cpp
... ... @@ -30,10 +30,9 @@
30 30  
31 31 static void printTemplate(const br::Template &t)
32 32 {
33   - printf("%s eyes: (%d, %d) (%d, %d)\n",
34   - qPrintable(t.file.fileName()),
35   - t.file.getInt("Affine_0_X"), t.file.getInt("Affine_0_Y"),
36   - t.file.getInt("Affine_1_X"), t.file.getInt("Affine_1_Y"));
  33 + const QPoint firstEye = t.file.get<QPoint>("Affine_0");
  34 + const QPoint secondEye = t.file.get<QPoint>("Affine_1");
  35 + printf("%s eyes: (%d, %d) (%d, %d)\n", qPrintable(t.file.fileName()), firstEye.x(), firstEye.y(), secondEye.x(), secondEye.y());
37 36 }
38 37  
39 38 int main(int argc, char *argv[])
... ...
app/examples/gender_estimation.cpp
... ... @@ -31,7 +31,7 @@ static void printTemplate(const br::Template &amp;t)
31 31 {
32 32 printf("%s gender: %s\n",
33 33 qPrintable(t.file.fileName()),
34   - t.file.getInt("Label") == 1 ? "Female" : "Male");
  34 + t.file.get<int>("Label") == 1 ? "Female" : "Male");
35 35 }
36 36  
37 37 int main(int argc, char *argv[])
... ...
app/openbr-gui/classifier.cpp
... ... @@ -39,19 +39,18 @@ void Classifier::_classify(File file)
39 39 {
40 40 QString key, value;
41 41 foreach (const File &f, Enroll(file.flat(), File("[algorithm=" + algorithm + "]"))) {
42   - qDebug() << f.flat();
43 42 if (!f.contains("Label"))
44 43 continue;
45 44  
46 45 if (algorithm == "GenderClassification") {
47 46 key = "Gender";
48   - value = (f.getInt("Label", 0) == 0 ? "Male" : "Female");
  47 + value = (f.get<int>("Label", 0) == 0 ? "Male" : "Female");
49 48 } else if (algorithm == "AgeRegression") {
50 49 key = "Age";
51   - value = QString::number(int(f.getFloat("Label", 0)+0.5)) + " Years";
  50 + value = QString::number(int(f.get<float>("Label", 0)+0.5)) + " Years";
52 51 } else {
53 52 key = algorithm;
54   - value = f.getString("Label");
  53 + value = f.get<QString>("Label");
55 54 }
56 55 break;
57 56 }
... ...
app/openbr-gui/gallerytoolbar.cpp
... ... @@ -117,7 +117,7 @@ void br::GalleryToolBar::checkWebcam()
117 117 void br::GalleryToolBar::enrollmentFinished()
118 118 {
119 119 if (files.isEmpty()) {
120   - if (input.getBool("enrollAll") && !tbWebcam.isChecked()) {
  120 + if (input.get<bool>("enrollAll", false) && !tbWebcam.isChecked()) {
121 121 QMessageBox msgBox;
122 122 msgBox.setText("Quality test failed.");
123 123 msgBox.setInformativeText("Enroll anyway?");
... ... @@ -127,7 +127,7 @@ void br::GalleryToolBar::enrollmentFinished()
127 127  
128 128 if (ret == QMessageBox::Ok) {
129 129 br::File file = input;
130   - file.setBool("enrollAll", false);
  130 + file.set("enrollAll", false);
131 131 enroll(file);
132 132 }
133 133 }
... ...
app/openbr-gui/templatemetadata.cpp
... ... @@ -28,7 +28,7 @@ void br::TemplateMetadata::setFile(const br::File &amp;file)
28 28 {
29 29 if (file.isNull()) lFile.clear();
30 30 else lFile.setText("<b>File:</b> " + file.fileName());
31   - lQuality.setText(QString("<b>Quality:</b> %1").arg(file.getBool("FTE") ? "Low" : "High"));
  31 + lQuality.setText(QString("<b>Quality:</b> %1").arg(file.get<bool>("FTE", false) ? "Low" : "High"));
32 32 foreach (const ConditionalClassifier &classifier, conditionalClassifiers)
33 33 if (classifier.action->isVisible()) classifier.classifier->classify(file);
34 34 }
... ...
app/openbr-gui/templateviewer.cpp
... ... @@ -39,10 +39,8 @@ void TemplateViewer::setFile(const File &amp;file_)
39 39  
40 40 // Update landmarks
41 41 landmarks.clear();
42   - if (file.contains("Affine_0_X") && file.contains("Affine_0_Y"))
43   - landmarks.append(QPointF(file.getFloat("Affine_0_X"), file.getFloat("Affine_0_Y")));
44   - if (file.contains("Affine_1_X") && file.contains("Affine_1_Y"))
45   - landmarks.append(QPointF(file.getFloat("Affine_1_X"), file.getFloat("Affine_1_Y")));
  42 + if (file.contains("Affine_0")) landmarks.append(file.get<QPointF>("Affine_0"));
  43 + if (file.contains("Affine_1")) landmarks.append(file.get<QPointF>("Affine_1"));
46 44 while (landmarks.size() < NumLandmarks)
47 45 landmarks.append(QPointF());
48 46 nearestLandmark = -1;
... ...
sdk/core/bee.cpp
... ... @@ -71,7 +71,7 @@ FileList BEE::readSigset(const QString &amp;sigset, bool ignoreMetadata)
71 71 newFile.append(file);
72 72 file = newFile;
73 73 } else if (!ignoreMetadata) {
74   - file.insert(key, value);
  74 + file.set(key, value);
75 75 }
76 76 }
77 77  
... ... @@ -99,7 +99,7 @@ void BEE::writeSigset(const QString &amp;sigset, const br::FileList &amp;files, bool ign
99 99 QStringList metadata;
100 100 if (!ignoreMetadata)
101 101 foreach (const QString &key, file.localKeys())
102   - metadata.append(key+"=\""+file.getString(key, "?")+"\"");
  102 + metadata.append(key+"=\""+file.get<QString>(key, "?")+"\"");
103 103 lines.append("\t<biometric-signature name=\"" + file.subject() +"\">");
104 104 lines.append("\t\t<presentation file-name=\"" + file.name + "\" " + metadata.join(" ") + "/>");
105 105 lines.append("\t</biometric-signature>");
... ... @@ -113,19 +113,19 @@ Mat readMatrix(const br::File &amp;matrix)
113 113 {
114 114 // Special case matrix construction
115 115 if (matrix == "Identity") {
116   - int rows = matrix.getInt("rows", -1);
117   - int columns = matrix.getInt("columns", -1);
118   - const int size = matrix.getInt("size", -1);
  116 + int rows = matrix.get<int>("rows", -1);
  117 + int columns = matrix.get<int>("columns", -1);
  118 + const int size = matrix.get<int>("size", -1);
119 119 if (size != -1) {
120 120 if (rows == -1) rows = size;
121 121 if (columns == -1) columns = size;
122 122 }
123   - const int step = matrix.getInt("step", 1);
  123 + const int step = matrix.get<int>("step", 1);
124 124 if (rows % step != 0) qFatal("Step does not divide rows evenly.");
125 125 if (columns % step != 0) qFatal("Step does not divide columns evenly.");
126 126  
127 127 if (sizeof(T) == sizeof(BEE::Mask_t)) {
128   - const bool selfSimilar = matrix.getBool("selfSimilar");
  128 + const bool selfSimilar = matrix.get<bool>("selfSimilar", false);
129 129  
130 130 Mat m(rows, columns, CV_8UC1);
131 131 m.setTo(BEE::NonMatch);
... ... @@ -171,8 +171,8 @@ Mat readMatrix(const br::File &amp;matrix)
171 171 file.close();
172 172  
173 173 Mat result;
174   - if (isDistance ^ matrix.getBool("negate")) m.convertTo(result, -1, -1);
175   - else result = m.clone();
  174 + if (isDistance ^ matrix.get<bool>("negate", false)) m.convertTo(result, -1, -1);
  175 + else result = m.clone();
176 176 return result;
177 177 }
178 178  
... ...
sdk/core/core.cpp
... ... @@ -194,7 +194,7 @@ struct AlgorithmCore
194 194  
195 195 void compare(File targetGallery, File queryGallery, File output)
196 196 {
197   - if (output.exists() && output.getBool("cache")) return;
  197 + if (output.exists() && output.get<bool>("cache", false)) return;
198 198 if (queryGallery == ".") queryGallery = targetGallery;
199 199  
200 200 QScopedPointer<Gallery> t, q;
... ... @@ -316,14 +316,14 @@ void br::Train(const File &amp;input, const File &amp;model)
316 316 {
317 317 qDebug("Training on %s%s", qPrintable(input.flat()),
318 318 model.isNull() ? "" : qPrintable(" to " + model.flat()));
319   - AlgorithmManager::getAlgorithm(model.getString("algorithm"))->train(input, model);
  319 + AlgorithmManager::getAlgorithm(model.get<QString>("algorithm"))->train(input, model);
320 320 }
321 321  
322 322 FileList br::Enroll(const File &input, const File &gallery)
323 323 {
324 324 qDebug("Enrolling %s%s", qPrintable(input.flat()),
325 325 gallery.isNull() ? "" : qPrintable(" to " + gallery.flat()));
326   - return AlgorithmManager::getAlgorithm(gallery.getString("algorithm"))->enroll(input, gallery);
  326 + return AlgorithmManager::getAlgorithm(gallery.get<QString>("algorithm"))->enroll(input, gallery);
327 327 }
328 328  
329 329 void br::Compare(const File &targetGallery, const File &queryGallery, const File &output)
... ... @@ -331,7 +331,7 @@ void br::Compare(const File &amp;targetGallery, const File &amp;queryGallery, const File
331 331 qDebug("Comparing %s and %s%s", qPrintable(targetGallery.flat()),
332 332 qPrintable(queryGallery.flat()),
333 333 output.isNull() ? "" : qPrintable(" to " + output.flat()));
334   - AlgorithmManager::getAlgorithm(output.getString("algorithm"))->compare(targetGallery, queryGallery, output);
  334 + AlgorithmManager::getAlgorithm(output.get<QString>("algorithm"))->compare(targetGallery, queryGallery, output);
335 335 }
336 336  
337 337 void br::Convert(const File &src, const File &dst)
... ...
sdk/core/plot.cpp
... ... @@ -119,8 +119,8 @@ float Evaluate(const QString &amp;simmat, const QString &amp;mask, const QString &amp;csv)
119 119 // Read files
120 120 const Mat scores = BEE::readSimmat(simmat);
121 121 File maskFile(mask);
122   - maskFile.insert("rows", scores.rows);
123   - maskFile.insert("columns", scores.cols);
  122 + maskFile.set("rows", scores.rows);
  123 + maskFile.set("columns", scores.cols);
124 124 const Mat masks = BEE::readMask(maskFile);
125 125 if (scores.size() != masks.size()) qFatal("Simmat/Mask size mismatch.");
126 126  
... ... @@ -416,7 +416,7 @@ struct RPlot
416 416 }
417 417 }
418 418  
419   - const QString &smooth = destination.getString("smooth", "");
  419 + const QString &smooth = destination.get<QString>("smooth", "");
420 420 major.smooth = !smooth.isEmpty() && (major.header == smooth) && (major.size > 1);
421 421 minor.smooth = !smooth.isEmpty() && (minor.header == smooth) && (minor.size > 1);
422 422 if (major.smooth) major.size = 1;
... ...
sdk/openbr_plugin.cpp
... ... @@ -58,10 +58,10 @@ QString File::hash() const
58 58 return QtUtils::shortTextHash(flat());
59 59 }
60 60  
61   -void File::append(const QHash<QString, QVariant> &metadata)
  61 +void File::append(const QMap<QString,QVariant> &metadata)
62 62 {
63 63 foreach (const QString &key, metadata.keys())
64   - insert(key, metadata[key]);
  64 + set(key, metadata[key]);
65 65 }
66 66  
67 67 void File::append(const File &other)
... ... @@ -70,7 +70,7 @@ void File::append(const File &amp;other)
70 70 if (name.isEmpty()) {
71 71 name = other.name;
72 72 } else {
73   - if (!contains("separator")) insert("separator", ";");
  73 + if (!contains("separator")) set("separator", ";");
74 74 name += value("separator").toString() + other.name;
75 75 }
76 76 }
... ... @@ -110,29 +110,6 @@ QVariant File::value(const QString &amp;key) const
110 110 return m_metadata.contains(key) ? m_metadata.value(key) : Globals->property(qPrintable(key));
111 111 }
112 112  
113   -QString File::subject(int label)
114   -{
115   - return Globals->classes.key(label, QString::number(label));
116   -}
117   -
118   -float File::label() const
119   -{
120   - const QVariant variant = value("Label");
121   - if (variant.isNull()) return -1;
122   -
123   - if (Globals->classes.contains(variant.toString()))
124   - return Globals->classes.value(variant.toString());
125   -
126   - bool ok;
127   - const float val = variant.toFloat(&ok);
128   - return ok ? val : -1;
129   -}
130   -
131   -void File::remove(const QString &key)
132   -{
133   - m_metadata.remove(key);
134   -}
135   -
136 113 void File::set(const QString &key, const QVariant &value)
137 114 {
138 115 if (key == "Label") {
... ... @@ -153,155 +130,90 @@ void File::set(const QString &amp;key, const QVariant &amp;value)
153 130 m_metadata.insert(key, value);
154 131 }
155 132  
156   -QVariant File::get(const QString &key) const
157   -{
158   - if (!contains(key)) qFatal("Missing key: %s", qPrintable(key));
159   - return value(key);
160   -}
161   -
162   -QVariant File::get(const QString &key, const QVariant &defaultValue) const
163   -{
164   - if (!contains(key)) return defaultValue;
165   - return value(key);
166   -}
167   -
168   -bool File::getBool(const QString &key) const
169   -{
170   - if (!contains(key)) return false;
171   - QString v = value(key).toString();
172   - if (v.isEmpty() || (v == "true")) return true;
173   - if (v == "false") return false;
174   - return v.toInt();
175   -}
176   -
177   -void File::setBool(const QString &key, bool value)
178   -{
179   - if (value) m_metadata.insert(key, QVariant());
180   - else m_metadata.remove(key);
181   -}
182   -
183   -int File::getInt(const QString &key) const
184   -{
185   - if (!contains(key)) qFatal("Missing key: %s", qPrintable(key));
186   - bool ok; int result = value(key).toInt(&ok);
187   - if (!ok) qFatal("Invalid conversion from: %s", qPrintable(getString(key)));
188   - return result;
189   -}
190   -
191   -int File::getInt(const QString &key, int defaultValue) const
192   -{
193   - if (!contains(key)) return defaultValue;
194   - bool ok; int result = value(key).toInt(&ok);
195   - if (!ok) return defaultValue;
196   - return result;
197   -}
198   -
199   -float File::getFloat(const QString &key) const
200   -{
201   - if (!contains(key)) qFatal("Missing key: %s", qPrintable(key));
202   - bool ok; float result = value(key).toFloat(&ok);
203   - if (!ok) qFatal("Invalid conversion from: %s", qPrintable(getString(key)));
204   - return result;
205   -}
206   -
207   -float File::getFloat(const QString &key, float defaultValue) const
  133 +QString File::subject(int label)
208 134 {
209   - if (!contains(key)) return defaultValue;
210   - bool ok; float result = value(key).toFloat(&ok);
211   - if (!ok) return defaultValue;
212   - return result;
  135 + return Globals->classes.key(label, QString::number(label));
213 136 }
214 137  
215   -QString File::getString(const QString &key) const
  138 +float File::label() const
216 139 {
217   - if (!contains(key)) qFatal("Missing key: %s", qPrintable(key));
218   - return value(key).toString();
219   -}
  140 + const QVariant variant = value("Label");
  141 + if (variant.isNull()) return -1;
220 142  
221   -QString File::getString(const QString &key, const QString &defaultValue) const
222   -{
223   - if (!contains(key)) return defaultValue;
224   - return value(key).toString();
225   -}
  143 + if (Globals->classes.contains(variant.toString()))
  144 + return Globals->classes.value(variant.toString());
226 145  
227   -QList<QPointF> File::landmarks() const
228   -{
229   - QList<QPointF> landmarks;
230   - foreach (const QVariant &landmark, value("Landmarks").toList())
231   - landmarks.append(landmark.toPointF());
232   - return landmarks;
  146 + bool ok;
  147 + const float val = variant.toFloat(&ok);
  148 + return ok ? val : -1;
233 149 }
234 150  
235   -QList<QPointF> File::namedLandmarks() const
  151 +QList<QPointF> File::namedPoints() const
236 152 {
237 153 QList<QPointF> landmarks;
238   - QStringList keys = localMetadata().keys();
239   - foreach (const QString &key, keys) {
240   - if (!key.endsWith("_X"))
241   - continue;
242   - QString keyBaseName = key.left(key.size()-2);
243   - if (!keys.contains(keyBaseName+"_Y") ||
244   - keys.contains(keyBaseName+"_Width") ||
245   - keys.contains(keyBaseName+"_Height") ||
246   - keys.contains(keyBaseName+"_Radius"))
247   - continue;
248   - landmarks.append(QPointF(getFloat(keyBaseName+"_X"), getFloat(keyBaseName+"_Y")));
  154 + foreach (const QString &key, localMetadata().keys()) {
  155 + const QVariant &variant = m_metadata[key];
  156 + if (variant.canConvert<QPointF>())
  157 + landmarks.append(variant.value<QPointF>());
249 158 }
250 159 return landmarks;
251 160 }
252 161  
253   -void File::appendLandmark(const QPointF &landmark)
  162 +QList<QPointF> File::points() const
254 163 {
255   - QList<QVariant> newLandmarks = m_metadata["Landmarks"].toList();
256   - newLandmarks.append(landmark);
257   - m_metadata["Landmarks"] = newLandmarks;
  164 + QList<QPointF> points;
  165 + foreach (const QVariant &point, m_metadata["Points"].toList())
  166 + points.append(point.toPointF());
  167 + return points;
258 168 }
259 169  
260   -void File::appendLandmarks(const QList<QPointF> &landmarks)
  170 +void File::appendPoint(const QPointF &point)
261 171 {
262   - QList<QVariant> newLandmarks = m_metadata["Landmarks"].toList();
263   - foreach (const QPointF &landmark, landmarks)
264   - newLandmarks.append(landmark);
265   - m_metadata["Landmarks"] = newLandmarks;
  172 + QList<QVariant> newPoints = m_metadata["Points"].toList();
  173 + newPoints.append(point);
  174 + m_metadata["Points"] = newPoints;
266 175 }
267 176  
268   -void File::setLandmarks(const QList<QPointF> &landmarks)
  177 +void File::appendPoints(const QList<QPointF> &points)
269 178 {
270   - QList<QVariant> landmarkList; landmarkList.reserve(landmarks.size());
271   - foreach (const QPointF &landmark, landmarks)
272   - landmarkList.append(landmark);
273   - m_metadata["Landmarks"] = landmarkList;
  179 + QList<QVariant> newPoints = m_metadata["Points"].toList();
  180 + foreach (const QPointF &point, points)
  181 + newPoints.append(point);
  182 + m_metadata["Points"] = newPoints;
274 183 }
275 184  
276   -QList<QRectF> File::ROIs() const
  185 +QList<QRectF> File::namedRects() const
277 186 {
278   - QList<QRectF> ROIs;
279   - foreach (const QVariant &ROI, value("ROIs").toList())
280   - ROIs.append(ROI.toRect());
281   - return ROIs;
  187 + QList<QRectF> rects;
  188 + foreach (const QString &key, localMetadata().keys()) {
  189 + const QVariant &variant = m_metadata[key];
  190 + if (variant.canConvert<QRectF>())
  191 + rects.append(variant.value<QRectF>());
  192 + }
  193 + return rects;
282 194 }
283 195  
284   -void File::appendROI(const QRectF &ROI)
  196 +QList<QRectF> File::rects() const
285 197 {
286   - QList<QVariant> newROIs = m_metadata["ROIs"].toList();
287   - newROIs.append(ROI);
288   - m_metadata["ROIs"] = newROIs;
  198 + QList<QRectF> rects;
  199 + foreach (const QVariant &rect, m_metadata["Rects"].toList())
  200 + rects.append(rect.toRect());
  201 + return rects;
289 202 }
290 203  
291   -void File::appendROIs(const QList<QRectF> &ROIs)
  204 +void File::appendRect(const QRectF &rect)
292 205 {
293   - QList<QVariant> newROIs = m_metadata["ROIs"].toList();
294   - foreach (const QRectF &ROI, ROIs)
295   - newROIs.append(ROI);
296   - m_metadata["ROIs"] = newROIs;
  206 + QList<QVariant> newRects = m_metadata["Rects"].toList();
  207 + newRects.append(rect);
  208 + m_metadata["Rects"] = newRects;
297 209 }
298 210  
299   -void File::setROIs(const QList<QRectF> &ROIs)
  211 +void File::appendRects(const QList<QRectF> &rects)
300 212 {
301   - QList<QVariant> ROIList; ROIList.reserve(ROIs.size());
302   - foreach (const QRectF &ROI, ROIs)
303   - ROIList.append(ROI);
304   - m_metadata["ROIs"] = ROIList;
  213 + QList<QVariant> newRects = m_metadata["Rects"].toList();
  214 + foreach (const QRectF &rect, rects)
  215 + newRects.append(rect);
  216 + m_metadata["Rects"] = newRects;
305 217 }
306 218  
307 219 /* File - private methods */
... ... @@ -325,10 +237,10 @@ void File::init(const QString &amp;file)
325 237 QStringList words = QtUtils::parse(parameters[i], '=');
326 238 QtUtils::checkArgsSize("File", words, 1, 2);
327 239 if (words.size() < 2) {
328   - if (unnamed) insertParameter(i, words[0]);
329   - else insert(words[0], QVariant());
  240 + if (unnamed) setParameter(i, words[0]);
  241 + else set(words[0], QVariant());
330 242 } else {
331   - insert(words[0], words[1]);
  243 + set(words[0], words[1]);
332 244 }
333 245 }
334 246 name = name.left(index);
... ... @@ -391,9 +303,8 @@ void FileList::sort(const QString&amp; key)
391 303 FileList sortedList;
392 304  
393 305 for (int i = 0; i < size(); i++) {
394   - if (at(i).contains(key)) {
395   - metadata.append(at(i).get(key).toString());
396   - }
  306 + if (at(i).contains(key))
  307 + metadata.append(at(i).get<QString>(key));
397 308 else sortedList.push_back(at(i));
398 309 }
399 310  
... ... @@ -416,7 +327,7 @@ QList&lt;int&gt; FileList::crossValidationPartitions() const
416 327 {
417 328 QList<int> crossValidationPartitions; crossValidationPartitions.reserve(size());
418 329 foreach (const File &f, *this)
419   - crossValidationPartitions.append(f.getInt("Cross_Validation_Partition", 0));
  330 + crossValidationPartitions.append(f.get<int>("Cross_Validation_Partition", 0));
420 331 return crossValidationPartitions;
421 332 }
422 333  
... ... @@ -424,7 +335,7 @@ int FileList::failures() const
424 335 {
425 336 int failures = 0;
426 337 foreach (const File &file, *this)
427   - if (file.getBool("FTO") || file.getBool("FTE"))
  338 + if (file.get<bool>("FTO", false) || file.get<bool>("FTE", false))
428 339 failures++;
429 340 return failures;
430 341 }
... ... @@ -447,9 +358,9 @@ TemplateList TemplateList::fromGallery(const br::File &amp;gallery)
447 358 foreach (const br::File &file, gallery.split()) {
448 359 QScopedPointer<Gallery> i(Gallery::make(file));
449 360 TemplateList newTemplates = i->read();
450   - newTemplates = newTemplates.mid(gallery.getInt("pos", 0), gallery.getInt("length", -1));
451   - if (gallery.getBool("reduce")) newTemplates = newTemplates.reduced();
452   - const int crossValidate = gallery.getInt("crossValidate");
  361 + newTemplates = newTemplates.mid(gallery.get<int>("pos", 0), gallery.get<int>("length", -1));
  362 + if (gallery.get<bool>("reduce", false)) newTemplates = newTemplates.reduced();
  363 + const int crossValidate = gallery.get<int>("crossValidate");
453 364 if (crossValidate > 0) srand(0);
454 365  
455 366 // If file is a Format not a Gallery
... ... @@ -460,11 +371,11 @@ TemplateList TemplateList::fromGallery(const br::File &amp;gallery)
460 371 for (int i=0; i<newTemplates.size(); i++) {
461 372 newTemplates[i].file.append(gallery.localMetadata());
462 373 newTemplates[i].file.append(file.localMetadata());
463   - newTemplates[i].file.insert("Index", i+templates.size());
464   - if (crossValidate > 0) newTemplates[i].file.insert("Cross_Validation_Partition", rand()%crossValidate);
  374 + newTemplates[i].file.set("Index", i+templates.size());
  375 + if (crossValidate > 0) newTemplates[i].file.set("Cross_Validation_Partition", rand()%crossValidate);
465 376 }
466 377  
467   - if (!templates.isEmpty() && gallery.getBool("merge")) {
  378 + if (!templates.isEmpty() && gallery.get<bool>("merge", false)) {
468 379 if (newTemplates.size() != templates.size())
469 380 qFatal("Inputs must be the same size in order to merge.");
470 381 for (int i=0; i<templates.size(); i++)
... ... @@ -1136,7 +1047,7 @@ static TemplateList Downsample(const TemplateList &amp;templates, const Transform *t
1136 1047 const int selectedLabel = selectedLabels[i];
1137 1048 QList<int> indices;
1138 1049 for (int j=0; j<allLabels.size(); j++)
1139   - if ((allLabels[j] == selectedLabel) && (!templates.value(j).file.getBool("FTE")))
  1050 + if ((allLabels[j] == selectedLabel) && (!templates.value(j).file.get<bool>("FTE", false)))
1140 1051 indices.append(j);
1141 1052  
1142 1053 std::random_shuffle(indices.begin(), indices.end());
... ... @@ -1320,7 +1231,7 @@ static void _project(const Transform *transform, const Template *src, Template *
1320 1231 } catch (...) {
1321 1232 qWarning("Exception triggered when processing %s with transform %s", qPrintable(src->file.flat()), qPrintable(transform->objectName()));
1322 1233 *dst = Template(src->file);
1323   - dst->file.setBool("FTE");
  1234 + dst->file.set("FTE", true);
1324 1235 }
1325 1236 }
1326 1237  
... ... @@ -1331,7 +1242,7 @@ static void _backProject(const Transform *transform, const Template *dst, Templa
1331 1242 } catch (...) {
1332 1243 qWarning("Exception triggered when processing %s with transform %s", qPrintable(src->file.flat()), qPrintable(transform->objectName()));
1333 1244 *src = Template(dst->file);
1334   - src->file.setBool("FTE");
  1245 + src->file.set("FTE", true);
1335 1246 }
1336 1247 }
1337 1248  
... ...
sdk/openbr_plugin.h
... ... @@ -128,8 +128,6 @@ void reset_##NAME() { NAME = DEFAULT; }
128 128 *
129 129 * Key | Value | Description
130 130 * --- | ---- | -----------
131   - * path | QString | Resolve complete file paths from file names
132   - * enrollAll | bool | Enroll zero or more templates per file
133 131 * separator | QString | Seperate #name into multiple files
134 132 * Index | int | Index of a template in a template list
135 133 * Label | float | Classification/Regression class
... ... @@ -145,8 +143,8 @@ void reset_##NAME() { NAME = DEFAULT; }
145 143 * Roll | float | Pose
146 144 * Pitch | float | Pose
147 145 * Yaw | float | Pose
148   - * Landmarks | QList<QPointF> | Landmark list
149   - * ROIs | QList<Rect> | Region Of Interest (ROI) list
  146 + * Points | QList<QPointF> | List of unnamed points
  147 + * Rects | QList<Rect> | List of unnamed rects
150 148 * Age | QString | Age used for demographic filtering
151 149 * _* | * | Reserved for internal use
152 150 */
... ... @@ -156,24 +154,26 @@ struct BR_EXPORT File
156 154  
157 155 File() {}
158 156 File(const QString &file) { init(file); } /*!< \brief Construct a file from a string. */
159   - File(const QString &file, const QVariant &label) { init(file); insert("Label", label); } /*!< \brief Construct a file from a string and assign a label. */
  157 + File(const QString &file, const QVariant &label) { init(file); set("Label", label); } /*!< \brief Construct a file from a string and assign a label. */
160 158 File(const char *file) { init(file); } /*!< \brief Construct a file from a c-style string. */
161 159 inline operator QString() const { return name; } /*!< \brief Returns #name. */
162 160 QString flat() const; /*!< \brief A stringified version of the file with metadata. */
163 161 QString hash() const; /*!< \brief A hash of the file. */
164   - inline void clear() { name.clear(); m_metadata.clear(); } /*!< \brief Clears the file's name and metadata. */
165 162  
166 163 inline QList<QString> localKeys() const { return m_metadata.keys(); } /*!< \brief Returns the private metadata keys. */
167   - inline QHash<QString,QVariant> localMetadata() const { return m_metadata; } /*!< \brief Returns the private metadata. */
168   - inline void insert(const QString &key, const QVariant &value) { set(key, value); } /*!< \brief Equivalent to set(). */
169   - void append(const QHash<QString,QVariant> &localMetadata); /*!< \brief Add new metadata fields. */
  164 + inline QMap<QString,QVariant> localMetadata() const { return m_metadata; } /*!< \brief Returns the private metadata. */
  165 +
  166 + void append(const QMap<QString,QVariant> &localMetadata); /*!< \brief Add new metadata fields. */
170 167 void append(const File &other); /*!< \brief Append another file using \c separator. */
  168 + inline File &operator+=(const QMap<QString,QVariant> &other) { append(other); return *this; } /*!< \brief Add new metadata fields. */
  169 + inline File &operator+=(const File &other) { append(other); return *this; } /*!< \brief Append another file using \c separator. */
  170 +
171 171 QList<File> split() const; /*!< \brief Split the file using \c separator. */
172 172 QList<File> split(const QString &separator) const; /*!< \brief Split the file. */
173 173  
174   - inline void insertParameter(int index, const QVariant &value) { insert("_Arg" + QString::number(index), value); } /*!< \brief Insert a keyless value. */
175   - inline bool containsParameter(int index) const { return m_metadata.contains("_Arg" + QString::number(index)); } /*!< \brief Check for the existence of a keyless value. */
176   - inline QVariant parameter(int index) const { return m_metadata.value("_Arg" + QString::number(index)); } /*!< \brief Retrieve a keyless value. */
  174 + inline void setParameter(int index, const QVariant &value) { set("_Arg" + QString::number(index), value); } /*!< \brief Insert a keyless value. */
  175 + inline bool containsParameter(int index) const { return contains("_Arg" + QString::number(index)); } /*!< \brief Check for the existence of a keyless value. */
  176 + inline QVariant getParameter(int index) const { return get<QVariant>("_Arg" + QString::number(index)); } /*!< \brief Retrieve a keyless value. */
177 177  
178 178 inline bool operator==(const char* other) const { return name == other; } /*!< \brief Compare name to c-style string. */
179 179 inline bool operator==(const File &other) const { return (name == other.name) && (m_metadata == other.m_metadata); } /*!< \brief Compare name and metadata for equality. */
... ... @@ -182,8 +182,6 @@ struct BR_EXPORT File
182 182 inline bool operator<=(const File &other) const { return name <= other.name; } /*!< \brief Compare name. */
183 183 inline bool operator>(const File &other) const { return name > other.name; } /*!< \brief Compare name. */
184 184 inline bool operator>=(const File &other) const { return name >= other.name; } /*!< \brief Compare name. */
185   - inline File &operator+=(const QHash<QString,QVariant> &other) { append(other); return *this; } /*!< \brief Add new metadata fields. */
186   - inline File &operator+=(const File &other) { append(other); return *this; } /*!< \brief Append another file using \c separator. */
187 185  
188 186 inline bool isNull() const { return name.isEmpty() && m_metadata.isEmpty(); } /*!< \brief Returns \c true if name and metadata are empty, \c false otherwise. */
189 187 inline bool isTerminal() const { return name == "terminal"; } /*!< \brief Returns \c true if #name is "terminal", \c false otherwise. */
... ... @@ -196,42 +194,53 @@ struct BR_EXPORT File
196 194  
197 195 bool contains(const QString &key) const; /*!< \brief Returns \c true if the key has an associated value, \c false otherwise. */
198 196 QVariant value(const QString &key) const; /*!< \brief Returns the value for the specified key. */
  197 + void set(const QString &key, const QVariant &value); /*!< \brief Insert or overwrite the metadata key with the specified value. */
  198 + inline void remove(const QString &key) { m_metadata.remove(key); } /*!< \brief Remove the metadata key. */
  199 +
  200 + /*!< \brief Returns a value for the key, throwing an error if the key does not exist. */
  201 + template <typename T>
  202 + T get(const QString &key) const
  203 + {
  204 + if (!contains(key)) qFatal("Missing key: %s", qPrintable(key));
  205 + QVariant variant = value(key);
  206 + if (!variant.canConvert<T>()) qFatal("Can't convert: %s", qPrintable(key));
  207 + return variant.value<T>();
  208 + }
  209 +
  210 + /*!< \brief Returns a value for the key, returning \em defaultValue if the key does not exist or can't be converted. */
  211 + template <typename T>
  212 + T get(const QString &key, const T &defaultValue) const
  213 + {
  214 + if (!contains(key)) return defaultValue;
  215 + QVariant variant = value(key);
  216 + if (!variant.canConvert<T>()) return defaultValue;
  217 + return variant.value<T>();
  218 + }
  219 +
199 220 static QString subject(int label); /*!< \brief Looks up the subject for the provided label. */
200 221 inline QString subject() const { return subject(label()); } /*!< \brief Looks up the subject from the file's label. */
201   - inline bool failed() const { return getBool("FTE") || getBool("FTO"); } /*!< \brief Returns \c true if the file failed to open or enroll, \c false otherwise. */
202   -
203   - void remove(const QString &key); /*!< \brief Remove the metadata key. */
204   - void set(const QString &key, const QVariant &value); /*!< \brief Insert or overwrite the metadata key with the specified value. */
205   - QVariant get(const QString &key) const; /*!< \brief Returns a QVariant for the key, throwing an error if the key does not exist. */
206   - QVariant get(const QString &key, const QVariant &value) const; /*!< \brief Returns a QVariant for the key, returning \em defaultValue if the key does not exist. */
207 222 float label() const; /*!< \brief Convenience function for retrieving the file's \c Label. */
208   - inline void setLabel(float label) { insert("Label", label); } /*!< \brief Convenience function for setting the file's \c Label. */
209   - bool getBool(const QString &key) const; /*!< \brief Returns a boolean value for the key. */
210   - void setBool(const QString &key, bool value = true); /*!< \brief Sets a boolean value for the key. */
211   - int getInt(const QString &key) const; /*!< \brief Returns an int value for the key, throwing an error if the key does not exist. */
212   - int getInt(const QString &key, int defaultValue) const; /*!< \brief Returns an int value for the key, returning \em defaultValue if the key does not exist. */
213   - float getFloat(const QString &key) const; /*!< \brief Returns a float value for the key, throwing an error if the key does not exist. */
214   - float getFloat(const QString &key, float defaultValue) const; /*!< \brief Returns a float value for the key, returning \em defaultValue if the key does not exist. */
215   - QString getString(const QString &key) const; /*!< \brief Returns a string value for the key, throwing an error if the key does not exist. */
216   - QString getString(const QString &key, const QString &defaultValue) const; /*!< \brief Returns a string value for the key, returning \em defaultValue if the key does not exist. */
217   -
218   - QList<QPointF> landmarks() const; /*!< \brief Returns the file's landmark list. */
219   - QList<QPointF> namedLandmarks() const; /*!< \brief Returns landmarks derived from metadata keys. */
220   - void appendLandmark(const QPointF &landmark); /*!< \brief Adds a landmark to the file's landmark list. */
221   - void appendLandmarks(const QList<QPointF> &landmarks); /*!< \brief Adds landmarks to the file's landmark list. */
222   - inline void clearLandmarks() { m_metadata["Landmarks"] = QList<QVariant>(); } /*!< \brief Clears the file's landmark list. */
223   - void setLandmarks(const QList<QPointF> &landmarks); /*!< \brief Assigns the file's landmark list. */
224   -
225   - QList<QRectF> ROIs() const; /*!< \brief Returns the file's ROI list. */
226   - void appendROI(const QRectF &ROI); /*!< \brief Adds a ROI to the file's ROI list. */
227   - void appendROIs(const QList<QRectF> &ROIs); /*!< \brief Adds ROIs to the file's ROI list. */
228   - inline void clearROIs() { m_metadata["ROIs"] = QList<QVariant>(); } /*!< \brief Clears the file's landmark list. */
229   - void setROIs(const QList<QRectF> &ROIs); /*!< \brief Assigns the file's landmark list. */
  223 + inline void setLabel(float label) { set("Label", label); } /*!< \brief Convenience function for setting the file's \c Label. */
  224 + inline bool failed() const { return get<bool>("FTE", false) || get<bool>("FTO", false); } /*!< \brief Returns \c true if the file failed to open or enroll, \c false otherwise. */
  225 +
  226 + QList<QPointF> namedPoints() const; /*!< \brief Returns points convertible from metadata keys. */
  227 + QList<QPointF> points() const; /*!< \brief Returns the file's points list. */
  228 + void appendPoint(const QPointF &point); /*!< \brief Adds a point to the file's point list. */
  229 + void appendPoints(const QList<QPointF> &points); /*!< \brief Adds landmarks to the file's landmark list. */
  230 + inline void clearPoints() { m_metadata["Points"] = QList<QVariant>(); } /*!< \brief Clears the file's landmark list. */
  231 + inline void setPoints(const QList<QPointF> &points) { clearPoints(); appendPoints(points); } /*!< \brief Overwrites the file's landmark list. */
  232 +
  233 + QList<QRectF> namedRects() const; /*!< \brief Returns rects convertible from metadata values. */
  234 + QList<QRectF> rects() const; /*!< \brief Returns the file's rects list. */
  235 + void appendRect(const QRectF &rect); /*!< \brief Adds a rect to the file's rect list. */
  236 + void appendRects(const QList<QRectF> &rects); /*!< \brief Adds rects to the file's rect list. */
  237 + inline void clearRects() { m_metadata["Rects"] = QList<QVariant>(); } /*!< \brief Clears the file's rect list. */
  238 + inline void setRects(const QList<QRectF> &rects) { clearRects(); appendRects(rects); } /*!< \brief Overwrites the file's rect list. */
230 239  
231 240 private:
232   - QHash<QString,QVariant> m_metadata;
233   - BR_EXPORT friend QDataStream &operator<<(QDataStream &stream, const File &file); /*!< */
234   - BR_EXPORT friend QDataStream &operator>>(QDataStream &stream, File &file); /*!< */
  241 + QMap<QString,QVariant> m_metadata;
  242 + BR_EXPORT friend QDataStream &operator<<(QDataStream &stream, const File &file);
  243 + BR_EXPORT friend QDataStream &operator>>(QDataStream &stream, File &file);
235 244  
236 245 void init(const QString &file);
237 246 };
... ...
sdk/plugins/cascade.cpp
... ... @@ -75,15 +75,15 @@ class CascadeTransform : public UntrainableTransform
75 75 {
76 76 CascadeClassifier *cascade = cascadeResource.acquire();
77 77 vector<Rect> rects;
78   - cascade->detectMultiScale(src, rects, 1.2, 5, src.file.getBool("enrollAll") ? 0 : CV_HAAR_FIND_BIGGEST_OBJECT, Size(minSize, minSize));
  78 + cascade->detectMultiScale(src, rects, 1.2, 5, src.file.get<bool>("enrollAll", false) ? 0 : CV_HAAR_FIND_BIGGEST_OBJECT, Size(minSize, minSize));
79 79 cascadeResource.release(cascade);
80 80  
81   - if (!src.file.getBool("enrollAll") && rects.empty())
  81 + if (!src.file.get<bool>("enrollAll", false) && rects.empty())
82 82 rects.push_back(Rect(0, 0, src.m().cols, src.m().rows));
83 83  
84 84 foreach (const Rect &rect, rects) {
85 85 dst += src;
86   - dst.file.appendROI(OpenCVUtils::fromRect(rect));
  86 + dst.file.appendRect(OpenCVUtils::fromRect(rect));
87 87 }
88 88 }
89 89 };
... ...
sdk/plugins/crop.cpp
... ... @@ -26,7 +26,7 @@ namespace br
26 26  
27 27 /*!
28 28 * \ingroup transforms
29   - * \brief Crops the regions of interest.
  29 + * \brief Crops the rectangular regions of interest.
30 30 * \author Josh Klontz \cite jklontz
31 31 */
32 32 class ROITransform : public UntrainableTransform
... ... @@ -35,8 +35,8 @@ class ROITransform : public UntrainableTransform
35 35  
36 36 void project(const Template &src, Template &dst) const
37 37 {
38   - foreach (const QRectF ROI, src.file.ROIs())
39   - dst += src.m()(OpenCVUtils::toRect(ROI));
  38 + foreach (const QRectF &rect, src.file.rects())
  39 + dst += src.m()(OpenCVUtils::toRect(rect));
40 40 }
41 41 };
42 42  
... ...
sdk/plugins/draw.cpp
... ... @@ -47,19 +47,19 @@ class DrawTransform : public UntrainableTransform
47 47 const Scalar verboseColor(255, 255, 0);
48 48 dst = src.m().clone();
49 49  
50   - QList<Point2f> landmarks = OpenCVUtils::toPoints(src.file.landmarks());
  50 + QList<Point2f> landmarks = OpenCVUtils::toPoints(src.file.points());
51 51  
52 52 if (unnamed) {
53 53 foreach (const Point2f &landmark, landmarks)
54 54 circle(dst, landmark, 3, color, -1);
55 55 }
56 56 if (named) {
57   - QList<Point2f> namedLandmarks = OpenCVUtils::toPoints(src.file.namedLandmarks());
  57 + QList<Point2f> namedLandmarks = OpenCVUtils::toPoints(src.file.namedPoints());
58 58 foreach (const Point2f &landmark, namedLandmarks)
59 59 circle(dst, landmark, 3, color);
60 60 }
61 61 if (ROI) {
62   - QList<Rect> ROIs = OpenCVUtils::toRects(src.file.ROIs());
  62 + QList<Rect> ROIs = OpenCVUtils::toRects(src.file.rects());
63 63 foreach (const Rect ROI, ROIs)
64 64 rectangle(dst, ROI, color);
65 65 }
... ... @@ -154,11 +154,11 @@ class EditTransform : public UntrainableTransform
154 154 {
155 155 (void) event;
156 156 if (flags) {
157   - QList<QRectF> ROIs = currentTemplate.file.ROIs();
158   - for (int i=ROIs.size()-1; i>=0; i--)
159   - if (ROIs[i].contains(x,y))
160   - ROIs.removeAt(i);
161   - currentTemplate.file.setROIs(ROIs);
  157 + QList<QRectF> rects = currentTemplate.file.rects();
  158 + for (int i=rects.size()-1; i>=0; i--)
  159 + if (rects[i].contains(x,y))
  160 + rects.removeAt(i);
  161 + currentTemplate.file.setRects(rects);
162 162 }
163 163  
164 164 Template temp;
... ...
sdk/plugins/eigen3.cpp
... ... @@ -228,7 +228,7 @@ class DFFSTransform : public Transform
228 228 void project(const Template &src, Template &dst) const
229 229 {
230 230 dst = src;
231   - dst.file.insert("DFFS", sqrt(pca.residualReconstructionError((*cvtFloat)(src))));
  231 + dst.file.set("DFFS", sqrt(pca.residualReconstructionError((*cvtFloat)(src))));
232 232 }
233 233  
234 234 void store(QDataStream &stream) const
... ...
sdk/plugins/eyes.cpp
... ... @@ -147,7 +147,7 @@ public:
147 147 private:
148 148 void project(const Template &src, Template &dst) const
149 149 {
150   - Rect roi = OpenCVUtils::toRect(src.file.ROIs().first());
  150 + Rect roi = OpenCVUtils::toRect(src.file.rects().first());
151 151  
152 152 Mat gray;
153 153 OpenCVUtils::cvtGray(src.m()(roi), gray);
... ... @@ -183,12 +183,10 @@ private:
183 183 float second_eye_y = (right_rect.y + maxLoc.y)*gray.rows/height+roi.y;
184 184  
185 185 dst = src;
186   - dst.file.appendLandmark(QPointF(first_eye_x, first_eye_y));
187   - dst.file.appendLandmark(QPointF(second_eye_x, second_eye_y));
188   - dst.file.insert("ASEF_Right_Eye_X", first_eye_x);
189   - dst.file.insert("ASEF_Right_Eye_Y", first_eye_y);
190   - dst.file.insert("ASEF_Left_Eye_X", second_eye_x);
191   - dst.file.insert("ASEF_Left_Eye_Y", second_eye_y);
  186 + dst.file.appendPoint(QPointF(first_eye_x, first_eye_y));
  187 + dst.file.appendPoint(QPointF(second_eye_x, second_eye_y));
  188 + dst.file.set("ASEF_Right_Eye", QPointF(first_eye_x, first_eye_y));
  189 + dst.file.set("ASEF_Left_Eye", QPointF(second_eye_x, second_eye_y));
192 190 }
193 191 };
194 192  
... ...
sdk/plugins/format.cpp
... ... @@ -217,11 +217,11 @@ class DefaultFormat : public Format
217 217 } else {
218 218 QString fileName = file.name;
219 219 if (!QFileInfo(fileName).exists()) {
220   - fileName = file.getString("path") + "/" + file.name;
  220 + fileName = file.get<QString>("path") + "/" + file.name;
221 221 if (!QFileInfo(fileName).exists()) {
222 222 fileName = file.fileName();
223 223 if (!QFileInfo(fileName).exists()) {
224   - fileName = file.getString("path") + "/" + file.fileName();
  224 + fileName = file.get<QString>("path") + "/" + file.fileName();
225 225 if (!QFileInfo(fileName).exists()) return t;
226 226 }
227 227 }
... ... @@ -604,7 +604,7 @@ class xmlFormat : public Format
604 604 (e.tagName() == "RPROFILE")) {
605 605 // Ignore these other image fields for now
606 606 } else {
607   - t.file.insert(e.tagName(), e.text());
  607 + t.file.set(e.tagName(), e.text());
608 608 }
609 609  
610 610 fileNode = fileNode.nextSibling();
... ... @@ -614,11 +614,11 @@ class xmlFormat : public Format
614 614  
615 615 // Calculate age
616 616 if (t.file.contains("DOB")) {
617   - const QDate dob = QDate::fromString(t.file.getString("DOB").left(10), "yyyy-MM-dd");
  617 + const QDate dob = QDate::fromString(t.file.get<QString>("DOB").left(10), "yyyy-MM-dd");
618 618 const QDate current = QDate::currentDate();
619 619 int age = current.year() - dob.year();
620 620 if (current.month() < dob.month()) age--;
621   - t.file.insert("Age", age);
  621 + t.file.set("Age", age);
622 622 }
623 623  
624 624 return t;
... ...
sdk/plugins/gallery.cpp
... ... @@ -22,13 +22,13 @@
22 22 #include <QSqlQuery>
23 23 #include <QSqlRecord>
24 24 #endif // BR_EMBEDDED
  25 +#include <opencv2/highgui/highgui.hpp>
25 26 #include <openbr_plugin.h>
26 27  
27 28 #include "NaturalStringCompare.h"
28 29 #include "core/bee.h"
29 30 #include "core/opencvutils.h"
30 31 #include "core/qtutils.h"
31   -#include <opencv2/highgui/highgui.hpp>
32 32  
33 33 namespace br
34 34 {
... ... @@ -47,7 +47,7 @@ class galGallery : public Gallery
47 47 void init()
48 48 {
49 49 gallery.setFileName(file);
50   - if (file.getBool("remove"))
  50 + if (file.get<bool>("remove", false))
51 51 gallery.remove();
52 52 QtUtils::touchDir(gallery);
53 53 if (!gallery.open(QFile::ReadWrite | QFile::Append))
... ... @@ -339,20 +339,33 @@ class csvGallery : public Gallery
339 339 {
340 340 if (files.isEmpty()) return;
341 341  
342   - QStringList keys;
  342 + QMap<QString,QVariant> samples;
343 343 foreach (const File &file, files)
344 344 foreach (const QString &key, file.localKeys())
345   - if (!keys.contains(key)) keys += key;
346   - qSort(keys);
  345 + if (!samples.contains(key))
  346 + samples.insert(key, file.value(key));
  347 +
  348 + QStringList lines;
  349 + lines.reserve(files.size()+1);
  350 +
  351 + { // Make header
  352 + QStringList words;
  353 + words.append("File");
  354 + foreach (const QString &key, samples.keys())
  355 + words.append(getCSVElement(key, samples[key], true));
  356 + lines.append(words.join(","));
  357 + }
347 358  
348   - const int rows = files.size();
349   - const int columns = keys.size();
350   - QSharedPointer<Output> output(Output::make(file, keys, files));
  359 + // Make table
  360 + foreach (const File &file, files) {
  361 + QStringList words;
  362 + words.append(file.name);
  363 + foreach (const QString &key, samples.keys())
  364 + words.append(getCSVElement(key, file.value(key), false));
  365 + lines.append(words.join(","));
  366 + }
351 367  
352   - for (int i=0; i<rows; i++)
353   - for (int j=0; j<columns; j++)
354   - if (keys[j] == "Label") output->setRelative(files[i].label(), i, j);
355   - else output->setRelative(files[i].getFloat(keys[j], std::numeric_limits<float>::quiet_NaN()), i, j);
  368 + QtUtils::writeFile(file, lines);
356 369 }
357 370  
358 371 TemplateList readBlock(bool *done)
... ... @@ -377,6 +390,25 @@ class csvGallery : public Gallery
377 390 {
378 391 files.append(t.file);
379 392 }
  393 +
  394 + static QString getCSVElement(const QString &key, const QVariant &value, bool header)
  395 + {
  396 + if (value.canConvert<QString>()) {
  397 + if (header) return key;
  398 + else return value.value<QString>();
  399 + } else if (value.canConvert<QPointF>()) {
  400 + const QPointF point = value.value<QPointF>();
  401 + if (header) return key+"_X,"+key+"_Y";
  402 + else return QString::number(point.x())+","+QString::number(point.y());
  403 + } else if (value.canConvert<QRectF>()) {
  404 + const QRectF rect = value.value<QRectF>();
  405 + if (header) return key+"_X,"+key+"_Y,"+key+"_Width,"+key+"_Height";
  406 + else return QString::number(rect.x())+","+QString::number(rect.y())+","+QString::number(rect.width())+","+QString::number(rect.height());
  407 + } else {
  408 + if (header) return key;
  409 + else return QString::number(std::numeric_limits<float>::quiet_NaN());
  410 + }
  411 + }
380 412 };
381 413  
382 414 BR_REGISTER(Gallery, csvGallery)
... ... @@ -465,9 +497,9 @@ class dbGallery : public Gallery
465 497 TemplateList readBlock(bool *done)
466 498 {
467 499 TemplateList templates;
468   - br::File import = file.getString("import", "");
469   - QString query = file.getString("query");
470   - QString subset = file.getString("subset", "");
  500 + br::File import = file.get<QString>("import", "");
  501 + QString query = file.get<QString>("query");
  502 + QString subset = file.get<QString>("subset", "");
471 503  
472 504 #ifndef BR_EMBEDDED
473 505 QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
... ...
sdk/plugins/hist.cpp
... ... @@ -174,7 +174,7 @@ class VarianceChangeDetectorTransform : public UntrainableTransform
174 174 int *buffer = new int[bins];
175 175  
176 176 float bestRatio = -std::numeric_limits<float>::max();
177   - QRect bestROI;
  177 + QRectF bestRect;
178 178  
179 179 const int rows = m.rows;
180 180 const int cols = m.cols/bins;
... ... @@ -202,7 +202,7 @@ class VarianceChangeDetectorTransform : public UntrainableTransform
202 202  
203 203 if (ratio > bestRatio) {
204 204 bestRatio = ratio;
205   - bestROI = QRect(j*radius, i*radius, scale*radius, scale*radius);
  205 + bestRect = QRect(j*radius, i*radius, scale*radius, scale*radius);
206 206 }
207 207 }
208 208 }
... ... @@ -210,7 +210,7 @@ class VarianceChangeDetectorTransform : public UntrainableTransform
210 210 }
211 211  
212 212 delete[] buffer;
213   - dst.file.appendROI(bestROI);
  213 + dst.file.appendRect(bestRect);
214 214 dst.file.setLabel(bestRatio);
215 215 }
216 216 };
... ...
sdk/plugins/keypoint.cpp
... ... @@ -54,13 +54,13 @@ class KeyPointDetectorTransform : public UntrainableTransform
54 54 featureDetector->detect(src, keyPoints);
55 55 } catch (...) {
56 56 qWarning("Key point detection failed for file %s", qPrintable(src.file.name));
57   - dst.file.setBool("FTE");
  57 + dst.file.set("FTE", true);
58 58 }
59 59  
60   - QList<Rect> ROIs;
  60 + QList<Rect> rects;
61 61 foreach (const KeyPoint &keyPoint, keyPoints)
62   - ROIs.append(Rect(keyPoint.pt.x, keyPoint.pt.y, keyPoint.size, keyPoint.size));
63   - dst.file.setROIs(OpenCVUtils::fromRects(ROIs));
  62 + rects.append(Rect(keyPoint.pt.x, keyPoint.pt.y, keyPoint.size, keyPoint.size));
  63 + dst.file.setRects(OpenCVUtils::fromRects(rects));
64 64 }
65 65 };
66 66  
... ... @@ -92,10 +92,10 @@ class KeyPointDescriptorTransform : public UntrainableTransform
92 92 {
93 93 std::vector<KeyPoint> keyPoints;
94 94 if (size == -1) {
95   - foreach (const QRectF &ROI, src.file.ROIs())
  95 + foreach (const QRectF &ROI, src.file.rects())
96 96 keyPoints.push_back(KeyPoint(ROI.x(), ROI.y(), (ROI.width() + ROI.height())/2));
97 97 } else {
98   - foreach (const QPointF &landmark, src.file.landmarks())
  98 + foreach (const QPointF &landmark, src.file.points())
99 99 keyPoints.push_back(KeyPoint(landmark.x(), landmark.y(), size));
100 100 }
101 101 descriptorExtractor->compute(src, keyPoints, dst);
... ... @@ -166,7 +166,7 @@ class SIFTDescriptorTransform : public UntrainableTransform
166 166 void project(const Template &src, Template &dst) const
167 167 {
168 168 std::vector<KeyPoint> keyPoints;
169   - foreach (const QPointF &val, src.file.landmarks())
  169 + foreach (const QPointF &val, src.file.points())
170 170 keyPoints.push_back(KeyPoint(val.x(), val.y(), size));
171 171  
172 172 Mat m;
... ... @@ -200,7 +200,7 @@ class GridTransform : public UntrainableTransform
200 200 for (float j=column_step/2; j<src.m().cols; j+=column_step)
201 201 landmarks.append(QPointF(i,j));
202 202 dst = src;
203   - dst.file.setLandmarks(landmarks);
  203 + dst.file.setPoints(landmarks);
204 204 }
205 205 };
206 206  
... ...
sdk/plugins/meta.cpp
... ... @@ -31,24 +31,24 @@ static TemplateList Expanded(const TemplateList &amp;templates)
31 31 TemplateList expanded;
32 32 foreach (const Template &t, templates) {
33 33 if (t.isEmpty()) {
34   - if (!t.file.getBool("enrollAll"))
  34 + if (!t.file.get<bool>("enrollAll", false))
35 35 expanded.append(t);
36 36 continue;
37 37 }
38 38  
39   - const bool fte = t.file.getBool("FTE");
40   - QList<QPointF> landmarks = t.file.landmarks();
41   - QList<QRectF> ROIs = t.file.ROIs();
42   - if (landmarks.size() % t.size() != 0) qFatal("Uneven landmark count.");
43   - if (ROIs.size() % t.size() != 0) qFatal("Uneven ROI count.");
44   - const int landmarkStep = landmarks.size() / t.size();
45   - const int ROIStep = ROIs.size() / t.size();
  39 + const bool fte = t.file.get<bool>("FTE", false);
  40 + QList<QPointF> points = t.file.points();
  41 + QList<QRectF> rects = t.file.rects();
  42 + if (points.size() % t.size() != 0) qFatal("Uneven point count.");
  43 + if (rects.size() % t.size() != 0) qFatal("Uneven rect count.");
  44 + const int pointStep = points.size() / t.size();
  45 + const int rectStep = rects.size() / t.size();
46 46  
47 47 for (int i=0; i<t.size(); i++) {
48   - if (!fte || !t.file.getBool("enrollAll")) {
  48 + if (!fte || !t.file.get<bool>("enrollAll", false)) {
49 49 expanded.append(Template(t.file, t[i]));
50   - expanded.last().file.setROIs(ROIs.mid(i*ROIStep, ROIStep));
51   - expanded.last().file.setLandmarks(landmarks.mid(i*landmarkStep, landmarkStep));
  50 + expanded.last().file.setRects(rects.mid(i*rectStep, rectStep));
  51 + expanded.last().file.setPoints(points.mid(i*pointStep, pointStep));
52 52 }
53 53 }
54 54 }
... ... @@ -233,7 +233,7 @@ class PipeTransform : public CompositeTransform
233 233 } catch (...) {
234 234 qWarning("Exception triggered when processing %s with transform %s", qPrintable(dst.file.flat()), qPrintable(f->objectName()));
235 235 src = Template(src.file);
236   - src.file.setBool("FTE");
  236 + src.file.set("FTE", true);
237 237 }
238 238 }
239 239 }
... ... @@ -247,7 +247,7 @@ class PipeTransform : public CompositeTransform
247 247 } catch (...) {
248 248 qWarning("Exception triggered when processing %s with transform %s", qPrintable(src.file.flat()), qPrintable(f->objectName()));
249 249 dst = Template(src.file);
250   - dst.file.setBool("FTE");
  250 + dst.file.set("FTE", true);
251 251 }
252 252 }
253 253 }
... ... @@ -310,7 +310,7 @@ protected:
310 310 } catch (...) {
311 311 qWarning("Exception triggered when processing %s with transform %s", qPrintable(src.file.flat()), qPrintable(f->objectName()));
312 312 dst = Template(src.file);
313   - dst.file.setBool("FTE");
  313 + dst.file.set("FTE", true);
314 314 }
315 315 }
316 316 }
... ... @@ -396,7 +396,7 @@ class ForkTransform : public CompositeTransform
396 396 } catch (...) {
397 397 qWarning("Exception triggered when processing %s with transform %s", qPrintable(src.file.flat()), qPrintable(f->objectName()));
398 398 dst = Template(src.file);
399   - dst.file.setBool("FTE");
  399 + dst.file.set("FTE", true);
400 400 }
401 401 }
402 402 }
... ... @@ -453,7 +453,7 @@ protected:
453 453 } catch (...) {
454 454 qWarning("Exception triggered when processing %s with transform %s", qPrintable(src.file.flat()), qPrintable(f->objectName()));
455 455 dst = Template(src.file);
456   - dst.file.setBool("FTE");
  456 + dst.file.set("FTE", true);
457 457 }
458 458 }
459 459 }
... ... @@ -648,7 +648,7 @@ class FTETransform : public Transform
648 648 foreach (const Template &t, projectedData) {
649 649 if (!t.file.contains(transform->objectName()))
650 650 qFatal("Matrix metadata missing key %s.", qPrintable(transform->objectName()));
651   - vals.append(t.file.getFloat(transform->objectName()));
  651 + vals.append(t.file.get<float>(transform->objectName()));
652 652 }
653 653 float q1, q3;
654 654 Common::Median(vals, &q1, &q3);
... ... @@ -660,11 +660,11 @@ class FTETransform : public Transform
660 660 {
661 661 Template projectedSrc;
662 662 transform->project(src, projectedSrc);
663   - const float val = projectedSrc.file.getFloat(transform->objectName());
  663 + const float val = projectedSrc.file.get<float>(transform->objectName());
664 664  
665 665 dst = src;
666   - dst.file.insert(transform->objectName(), val);
667   - dst.file.insert("FTE", (val < min) || (val > max));
  666 + dst.file.set(transform->objectName(), val);
  667 + dst.file.set("FTE", (val < min) || (val > max));
668 668 }
669 669 };
670 670  
... ...
sdk/plugins/misc.cpp
... ... @@ -44,7 +44,7 @@ class OpenTransform : public UntrainableMetaTransform
44 44 dst.append(t);
45 45 dst.file.append(t.file.localMetadata());
46 46 }
47   - dst.file.insert("FTO", dst.isEmpty());
  47 + dst.file.set("FTO", dst.isEmpty());
48 48 }
49 49 };
50 50  
... ... @@ -282,7 +282,7 @@ class RenameTransform : public UntrainableMetaTransform
282 282 {
283 283 dst = src;
284 284 if (dst.file.localKeys().contains(find)) {
285   - dst.file.insert(replace, dst.file.get(find));
  285 + dst.file.set(replace, dst.file.value(find));
286 286 dst.file.remove(find);
287 287 }
288 288 }
... ... @@ -308,7 +308,7 @@ class RenameFirstTransform : public UntrainableMetaTransform
308 308 dst = src;
309 309 foreach (const QString &key, find)
310 310 if (dst.file.localKeys().contains(key)) {
311   - dst.file.insert(replace, dst.file.get(key));
  311 + dst.file.set(replace, dst.file.value(key));
312 312 dst.file.remove(key);
313 313 break;
314 314 }
... ...
sdk/plugins/output.cpp
... ... @@ -106,7 +106,7 @@ class meltOutput : public MatrixOutput
106 106 const bool genuineOnly = file.contains("Genuine") && !file.contains("Impostor");
107 107 const bool impostorOnly = file.contains("Impostor") && !file.contains("Genuine");
108 108  
109   - QHash<QString,QVariant> args = file.localMetadata();
  109 + QMap<QString,QVariant> args = file.localMetadata();
110 110 args.remove("Genuine");
111 111 args.remove("Impostor");
112 112  
... ... @@ -165,9 +165,9 @@ class rrOutput : public MatrixOutput
165 165 ~rrOutput()
166 166 {
167 167 if (file.isNull() || targetFiles.isEmpty() || queryFiles.isEmpty()) return;
168   - const int limit = file.getInt("limit", 20);
169   - const bool byLine = file.getBool("byLine");
170   - const float threshold = file.getFloat("threshold", -std::numeric_limits<float>::max());
  168 + const int limit = file.get<int>("limit", 20);
  169 + const bool byLine = file.get<bool>("byLine", false);
  170 + const float threshold = file.get<float>("threshold", -std::numeric_limits<float>::max());
171 171  
172 172 QStringList lines;
173 173  
... ... @@ -279,7 +279,7 @@ class rankOutput : public MatrixOutput
279 279 typedef QPair<float,int> Pair;
280 280 int rank = 1;
281 281 foreach (const Pair &pair, Common::Sort(OpenCVUtils::matrixToVector(data.row(i)), true)) {
282   - if(targetFiles[pair.second].getString("Label") == queryFiles[i].getString("Label")) {
  282 + if(targetFiles[pair.second].get<QString>("Label") == queryFiles[i].get<QString>("Label")) {
283 283 ranks.append(rank);
284 284 positions.append(pair.second);
285 285 scores.append(pair.first);
... ... @@ -347,10 +347,10 @@ class tailOutput : public Output
347 347 void initialize(const FileList &targetFiles, const FileList &queryFiles)
348 348 {
349 349 Output::initialize(targetFiles, queryFiles);
350   - threshold = file.getFloat("threshold", -std::numeric_limits<float>::max());
351   - atLeast = file.getInt("atLeast", 1);
352   - atMost = file.getInt("atMost", std::numeric_limits<int>::max());
353   - args = file.getBool("args");
  350 + threshold = file.get<float>("threshold", -std::numeric_limits<float>::max());
  351 + atLeast = file.get<int>("atLeast", 1);
  352 + atMost = file.get<int>("atMost", std::numeric_limits<int>::max());
  353 + args = file.get<bool>("args", false);
354 354 lastValue = -std::numeric_limits<float>::max();
355 355 }
356 356  
... ... @@ -462,9 +462,9 @@ class histOutput : public Output
462 462 void initialize(const FileList &targetFiles, const FileList &queryFiles)
463 463 {
464 464 Output::initialize(targetFiles, queryFiles);
465   - min = file.getFloat("min", -5);
466   - max = file.getFloat("max", 5);
467   - step = file.getFloat("step", 0.1);
  465 + min = file.get<float>("min", -5);
  466 + max = file.get<float>("max", 5);
  467 + step = file.get<float>("step", 0.1);
468 468 bins = QVector<int>((max-min)/step, 0);
469 469 }
470 470  
... ...
sdk/plugins/pixel.cpp
... ... @@ -120,7 +120,7 @@ class PerPixelClassifierTransform : public MetaTransform
120 120 uchar *psrc = src[n].ptr();
121 121 ptemp[n] = psrc[index];
122 122 }
123   - cv::Mat labelMat = src.file.get("labels").value<cv::Mat>();
  123 + cv::Mat labelMat = src.file.value("labels").value<cv::Mat>();
124 124 uchar* plabel = labelMat.ptr();
125 125 temp.file.setLabel(plabel[index]);
126 126  
... ...
sdk/plugins/quality.cpp
... ... @@ -53,8 +53,8 @@ class ImpostorUniquenessMeasureTransform : public Transform
53 53 {
54 54 dst = src;
55 55 float ium = calculateIUM(src, impostors);
56   - dst.file.insert("Impostor_Uniqueness_Measure", ium);
57   - dst.file.insert("Impostor_Uniqueness_Measure_Bin", ium < mean-stddev ? 0 : (ium < mean+stddev ? 1 : 2));
  56 + dst.file.set("Impostor_Uniqueness_Measure", ium);
  57 + dst.file.set("Impostor_Uniqueness_Measure_Bin", ium < mean-stddev ? 0 : (ium < mean+stddev ? 1 : 2));
58 58 }
59 59  
60 60 void store(QDataStream &stream) const
... ...
sdk/plugins/random.cpp
... ... @@ -155,7 +155,7 @@ class RndPointTransform : public Transform
155 155 void project(const Template &src, Template &dst) const
156 156 {
157 157 dst = src;
158   - dst.file.appendLandmark(QPointF(src.m().cols * x, src.m().rows * y));
  158 + dst.file.appendPoint(QPointF(src.m().cols * x, src.m().rows * y));
159 159 }
160 160 };
161 161  
... ...
sdk/plugins/regions.cpp
... ... @@ -148,7 +148,7 @@ class RectFromLandmarksTransform : public UntrainableTransform
148 148  
149 149 void project(const Template &src, Template &dst) const
150 150 {
151   - if (src.file.landmarks().isEmpty()) {
  151 + if (src.file.points().isEmpty()) {
152 152 qWarning("No landmarks");
153 153 dst = src;
154 154 return;
... ... @@ -160,12 +160,12 @@ class RectFromLandmarksTransform : public UntrainableTransform
160 160 maxX = maxY = -std::numeric_limits<int>::max();
161 161  
162 162 foreach(int index, indices) {
163   - if (src.file.landmarks().size() > index+1) {
164   - if (src.file.landmarks()[index].x() < minX) minX = src.file.landmarks()[index].x();
165   - if (src.file.landmarks()[index].x() > maxX) maxX = src.file.landmarks()[index].x();
166   - if (src.file.landmarks()[index].y() < minY) minY = src.file.landmarks()[index].y();
167   - if (src.file.landmarks()[index].y() > maxY) maxY = src.file.landmarks()[index].y();
168   - dst.file.appendLandmark(src.file.landmarks()[index]);
  163 + if (src.file.points().size() > index+1) {
  164 + if (src.file.points()[index].x() < minX) minX = src.file.points()[index].x();
  165 + if (src.file.points()[index].x() > maxX) maxX = src.file.points()[index].x();
  166 + if (src.file.points()[index].y() < minY) minY = src.file.points()[index].y();
  167 + if (src.file.points()[index].y() > maxY) maxY = src.file.points()[index].y();
  168 + dst.file.appendPoint(src.file.points()[index]);
169 169 }
170 170 }
171 171  
... ...
sdk/plugins/register.cpp
... ... @@ -67,17 +67,14 @@ class AffineTransform : public UntrainableTransform
67 67 else dstPoints[2] = Point2f(x3*width, y3*height);
68 68  
69 69 Point2f srcPoints[3];
70   - if (src.file.contains("Affine_0_X") &&
71   - src.file.contains("Affine_0_Y") &&
72   - src.file.contains("Affine_1_X") &&
73   - src.file.contains("Affine_1_Y") &&
74   - (src.file.contains("Affine_2_X") || twoPoints) &&
75   - (src.file.contains("Affine_2_Y") || twoPoints)) {
76   - srcPoints[0] = Point2f(src.file.getFloat("Affine_0_X"), src.file.getFloat("Affine_0_Y"));
77   - srcPoints[1] = Point2f(src.file.getFloat("Affine_1_X"), src.file.getFloat("Affine_1_Y"));
78   - if (!twoPoints) srcPoints[2] = Point2f(src.file.getFloat("Affine_2_X"), src.file.getFloat("Affine_2_Y"));
  70 + if (src.file.contains("Affine_0") &&
  71 + src.file.contains("Affine_1") &&
  72 + (src.file.contains("Affine_2") || twoPoints)) {
  73 + srcPoints[0] = OpenCVUtils::toPoint(src.file.get<QPointF>("Affine_0"));
  74 + srcPoints[1] = OpenCVUtils::toPoint(src.file.get<QPointF>("Affine_1"));
  75 + if (!twoPoints) srcPoints[2] = OpenCVUtils::toPoint(src.file.get<QPointF>("Affine_2"));
79 76 } else {
80   - const QList<Point2f> landmarks = OpenCVUtils::toPoints(src.file.landmarks());
  77 + const QList<Point2f> landmarks = OpenCVUtils::toPoints(src.file.points());
81 78  
82 79 if ((landmarks.size() < 2) || (!twoPoints && (landmarks.size() < 3))) {
83 80 resize(src, dst, Size(width, height));
... ... @@ -87,14 +84,9 @@ class AffineTransform : public UntrainableTransform
87 84 srcPoints[1] = landmarks[1];
88 85 if (!twoPoints) srcPoints[2] = landmarks[2];
89 86  
90   - dst.file.insert("Affine_0_X", landmarks[0].x);
91   - dst.file.insert("Affine_0_Y", landmarks[0].y);
92   - dst.file.insert("Affine_1_X", landmarks[1].x);
93   - dst.file.insert("Affine_1_Y", landmarks[1].y);
94   - if (!twoPoints) {
95   - dst.file.insert("Affine_2_X", landmarks[2].x);
96   - dst.file.insert("Affine_2_Y", landmarks[2].y);
97   - }
  87 + dst.file.set("Affine_0", OpenCVUtils::fromPoint(landmarks[0]));
  88 + dst.file.set("Affine_1", OpenCVUtils::fromPoint(landmarks[1]));
  89 + if (!twoPoints) dst.file.set("Affine_2", OpenCVUtils::fromPoint(landmarks[2]));
98 90 }
99 91 }
100 92 if (twoPoints) srcPoints[2] = getThirdAffinePoint(srcPoints[0], srcPoints[1]);
... ...
sdk/plugins/validate.cpp
... ... @@ -22,7 +22,7 @@ class CrossValidateTransform : public MetaTransform
22 22 int numPartitions = 0;
23 23 QList<int> partitions; partitions.reserve(data.size());
24 24 foreach (const File &file, data.files()) {
25   - partitions.append(file.getInt("Cross_Validation_Partition", 0));
  25 + partitions.append(file.get<int>("Cross_Validation_Partition", 0));
26 26 numPartitions = std::max(numPartitions, partitions.last()+1);
27 27 }
28 28  
... ... @@ -48,7 +48,7 @@ class CrossValidateTransform : public MetaTransform
48 48  
49 49 void project(const Template &src, Template &dst) const
50 50 {
51   - transforms[src.file.getInt("Cross_Validation_Partition", 0)]->project(src, dst);
  51 + transforms[src.file.get<int>("Cross_Validation_Partition", 0)]->project(src, dst);
52 52 }
53 53  
54 54 void store(QDataStream &stream) const
... ... @@ -82,8 +82,8 @@ class CrossValidateDistance : public Distance
82 82  
83 83 float compare(const Template &a, const Template &b) const
84 84 {
85   - const int partitionA = a.file.getInt("Cross_Validation_Partition", 0);
86   - const int partitionB = b.file.getInt("Cross_Validation_Partition", 0);
  85 + const int partitionA = a.file.get<int>("Cross_Validation_Partition", 0);
  86 + const int partitionB = b.file.get<int>("Cross_Validation_Partition", 0);
87 87 return (partitionA != partitionB) ? -std::numeric_limits<float>::max() : 0;
88 88 }
89 89 };
... ... @@ -104,7 +104,7 @@ class FilterDistance : public Distance
104 104 (void) b; // Query template isn't checked
105 105 foreach (const QString &key, Globals->filters.keys()) {
106 106 bool keep = false;
107   - const QString metadata = a.file.getString(key, "");
  107 + const QString metadata = a.file.get<QString>(key, "");
108 108 if (metadata.isEmpty()) continue;
109 109 foreach (const QString &value, Globals->filters[key]) {
110 110 if (metadata == value) {
... ...
sdk/plugins/wavelet.cpp
... ... @@ -189,11 +189,11 @@ class GaborJetTransform : public UntrainableTransform
189 189  
190 190 void project(const Template &src, Template &dst) const
191 191 {
192   - const QList<QPointF> landmarks = src.file.landmarks();
193   - dst = Mat(landmarks.size(), kReals.size(), CV_32FC1);
194   - for (int i=0; i<landmarks.size(); i++)
  192 + const QList<QPointF> points = src.file.points();
  193 + dst = Mat(points.size(), kReals.size(), CV_32FC1);
  194 + for (int i=0; i<points.size(); i++)
195 195 for (int j=0; j<kReals.size(); j++)
196   - dst.m().at<float>(i,j) = response(src, landmarks[i], kReals[j], kImaginaries[j], component);
  196 + dst.m().at<float>(i,j) = response(src, points[i], kReals[j], kImaginaries[j], component);
197 197 }
198 198 };
199 199  
... ...