Commit c2634f0f043353582755dcc3889ac15da0210e76

Authored by Josh Klontz
2 parents 6023480a fea31bb9

Merge branch 'master' into janus

.gitignore
@@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
4 data/*/img 4 data/*/img
5 data/*/vid 5 data/*/vid
6 data/PCSO/* 6 data/PCSO/*
  7 +data/lfpw
7 build* 8 build*
8 scripts/results 9 scripts/results
9 10
@@ -38,3 +39,4 @@ scripts/results @@ -38,3 +39,4 @@ scripts/results
38 ### autogenerated sigsets ### 39 ### autogenerated sigsets ###
39 data/INRIAPerson/sigset 40 data/INRIAPerson/sigset
40 data/KTH/sigset 41 data/KTH/sigset
  42 +
openbr/core/core.cpp
@@ -70,7 +70,7 @@ struct AlgorithmCore @@ -70,7 +70,7 @@ struct AlgorithmCore
70 70
71 if (!distance.isNull()) { 71 if (!distance.isNull()) {
72 qDebug("Projecting Enrollment"); 72 qDebug("Projecting Enrollment");
73 - data >> *transform; 73 + data >> *downcast;
74 74
75 qDebug("Training Comparison"); 75 qDebug("Training Comparison");
76 distance->train(data); 76 distance->train(data);
@@ -490,9 +490,18 @@ void br::Cat(const QStringList &inputGalleries, const QString &outputGallery) @@ -490,9 +490,18 @@ void br::Cat(const QStringList &inputGalleries, const QString &outputGallery)
490 } 490 }
491 } 491 }
492 492
493 -QSharedPointer<br::Transform> br::Transform::fromAlgorithm(const QString &algorithm) 493 +QSharedPointer<br::Transform> br::Transform::fromAlgorithm(const QString &algorithm, bool preprocess)
494 { 494 {
495 - return AlgorithmManager::getAlgorithm(algorithm)->transform; 495 + if (!preprocess)
  496 + return AlgorithmManager::getAlgorithm(algorithm)->transform;
  497 + else {
  498 + QSharedPointer<Transform> orig_tform = AlgorithmManager::getAlgorithm(algorithm)->transform;
  499 + QSharedPointer<Transform> newRoot = QSharedPointer<Transform>(Transform::make("Stream(Identity)", NULL));
  500 + WrapperTransform * downcast = dynamic_cast<WrapperTransform *> (newRoot.data());
  501 + downcast->transform = orig_tform.data();
  502 + downcast->init();
  503 + return newRoot;
  504 + }
496 } 505 }
497 506
498 QSharedPointer<br::Distance> br::Distance::fromAlgorithm(const QString &algorithm) 507 QSharedPointer<br::Distance> br::Distance::fromAlgorithm(const QString &algorithm)
openbr/openbr.cpp
@@ -341,6 +341,12 @@ int br_img_channels(br_template tmpl) @@ -341,6 +341,12 @@ int br_img_channels(br_template tmpl)
341 return t->m().channels(); 341 return t->m().channels();
342 } 342 }
343 343
  344 +bool br_img_is_empty(br_template tmpl)
  345 +{
  346 + Template *t = reinterpret_cast<Template*>(tmpl);
  347 + return t->m().empty();
  348 +}
  349 +
344 void br_set_filename(br_template tmpl, const char *filename) 350 void br_set_filename(br_template tmpl, const char *filename)
345 { 351 {
346 Template *t = reinterpret_cast<Template*>(tmpl); 352 Template *t = reinterpret_cast<Template*>(tmpl);
@@ -356,6 +362,12 @@ br_template_list br_enroll_template(br_template tmpl) @@ -356,6 +362,12 @@ br_template_list br_enroll_template(br_template tmpl)
356 return (br_template_list)tl; 362 return (br_template_list)tl;
357 } 363 }
358 364
  365 +void br_enroll_template_list(br_template_list tl)
  366 +{
  367 + TemplateList *realTL = reinterpret_cast<TemplateList*>(tl);
  368 + Enroll(*realTL);
  369 +}
  370 +
359 br_template br_get_template(br_template_list tl, int index) 371 br_template br_get_template(br_template_list tl, int index)
360 { 372 {
361 TemplateList *realTL = reinterpret_cast<TemplateList*>(tl); 373 TemplateList *realTL = reinterpret_cast<TemplateList*>(tl);
openbr/openbr.h
@@ -467,6 +467,10 @@ BR_EXPORT int br_img_cols(br_template tmpl); @@ -467,6 +467,10 @@ BR_EXPORT int br_img_cols(br_template tmpl);
467 */ 467 */
468 BR_EXPORT int br_img_channels(br_template tmpl); 468 BR_EXPORT int br_img_channels(br_template tmpl);
469 /*! 469 /*!
  470 + * \brief Returns if the image is empty.
  471 + */
  472 +BR_EXPORT bool br_img_is_empty(br_template tmpl);
  473 +/*!
470 * \brief Set the filename for a template. 474 * \brief Set the filename for a template.
471 */ 475 */
472 BR_EXPORT void br_set_filename(br_template tmpl, const char *filename); 476 BR_EXPORT void br_set_filename(br_template tmpl, const char *filename);
@@ -476,6 +480,11 @@ BR_EXPORT void br_set_filename(br_template tmpl, const char *filename); @@ -476,6 +480,11 @@ BR_EXPORT void br_set_filename(br_template tmpl, const char *filename);
476 */ 480 */
477 BR_EXPORT br_template_list br_enroll_template(br_template tmpl); 481 BR_EXPORT br_template_list br_enroll_template(br_template tmpl);
478 /*! 482 /*!
  483 + * \brief Enroll a br::TemplateList from the C API!
  484 + * \param tmpl Pointer to a br::TemplateList.
  485 + */
  486 +BR_EXPORT void br_enroll_template_list(br_template_list tl);
  487 +/*!
479 * \brief Get a pointer to a br::Template at a specified index. 488 * \brief Get a pointer to a br::Template at a specified index.
480 * \param tl Pointer to a br::TemplateList. 489 * \param tl Pointer to a br::TemplateList.
481 * \param index The index of the br::Template. 490 * \param index The index of the br::Template.
openbr/openbr_plugin.cpp
@@ -1184,10 +1184,6 @@ Transform *Transform::make(QString str, QObject *parent) @@ -1184,10 +1184,6 @@ Transform *Transform::make(QString str, QObject *parent)
1184 if (Globals->abbreviations.contains(str)) 1184 if (Globals->abbreviations.contains(str))
1185 return make(Globals->abbreviations[str], parent); 1185 return make(Globals->abbreviations[str], parent);
1186 1186
1187 - { // Check for use of '!' as shorthand for Expand  
1188 - str.replace("!","+Expand+");  
1189 - }  
1190 -  
1191 //! [Make a pipe] 1187 //! [Make a pipe]
1192 { // Check for use of '+' as shorthand for Pipe(...) 1188 { // Check for use of '+' as shorthand for Pipe(...)
1193 QStringList words = parse(str, '+'); 1189 QStringList words = parse(str, '+');
openbr/openbr_plugin.h
@@ -1105,7 +1105,7 @@ public: @@ -1105,7 +1105,7 @@ public:
1105 1105
1106 virtual ~Transform() {} 1106 virtual ~Transform() {}
1107 static Transform *make(QString str, QObject *parent); /*!< \brief Make a transform from a string. */ 1107 static Transform *make(QString str, QObject *parent); /*!< \brief Make a transform from a string. */
1108 - static QSharedPointer<Transform> fromAlgorithm(const QString &algorithm); /*!< \brief Retrieve an algorithm's transform. */ 1108 + static QSharedPointer<Transform> fromAlgorithm(const QString &algorithm, bool preprocess=true); /*!< \brief Retrieve an algorithm's transform. If preprocess is true, attaches a stream transform as the root of the algorithm*/
1109 1109
1110 virtual Transform *clone() const; /*!< \brief Copy the transform. */ 1110 virtual Transform *clone() const; /*!< \brief Copy the transform. */
1111 1111
@@ -1124,6 +1124,7 @@ public: @@ -1124,6 +1124,7 @@ public:
1124 1124
1125 /*!< \brief Apply the transform to a single template. Typically used by independent transforms */ 1125 /*!< \brief Apply the transform to a single template. Typically used by independent transforms */
1126 virtual void project(const Template &src, Template &dst) const = 0; 1126 virtual void project(const Template &src, Template &dst) const = 0;
  1127 +
1127 /*!< \brief Apply the transform, taking the full template list as input. 1128 /*!< \brief Apply the transform, taking the full template list as input.
1128 * A TemplateList is what is typically passed from transform to transform. Transforms that just 1129 * A TemplateList is what is typically passed from transform to transform. Transforms that just
1129 * need to operatoe on a single template at a time (and want to output exactly 1 template) can implement 1130 * need to operatoe on a single template at a time (and want to output exactly 1 template) can implement
@@ -1208,7 +1209,9 @@ public: @@ -1208,7 +1209,9 @@ public:
1208 * and copy enough of their state that projectUpdate can safely be called on the original 1209 * and copy enough of their state that projectUpdate can safely be called on the original
1209 * instance, and the copy concurrently. 1210 * instance, and the copy concurrently.
1210 */ 1211 */
1211 - virtual Transform * smartCopy() { return this;} 1212 + virtual Transform * smartCopy(bool & newTransform) { newTransform=false; return this;}
  1213 +
  1214 + virtual Transform * smartCopy() {bool junk; return smartCopy(junk);}
1212 1215
1213 /*! 1216 /*!
1214 * \brief Recursively retrieve a named event, returns NULL if an event is not found. 1217 * \brief Recursively retrieve a named event, returns NULL if an event is not found.
openbr/plugins/algorithms.cpp
@@ -31,14 +31,14 @@ class AlgorithmsInitializer : public Initializer @@ -31,14 +31,14 @@ class AlgorithmsInitializer : public Initializer
31 void initialize() const 31 void initialize() const
32 { 32 {
33 // Face 33 // Face
34 - Globals->abbreviations.insert("FaceRecognition", "FaceDetection!<FaceRecognitionRegistration>!<FaceRecognitionExtraction>+<FaceRecognitionEmbedding>+<FaceRecognitionQuantization>:MatchProbability(ByteL1)");  
35 - Globals->abbreviations.insert("GenderClassification", "FaceDetection!<FaceClassificationRegistration>!<FaceClassificationExtraction>+<GenderClassifier>+Discard");  
36 - Globals->abbreviations.insert("AgeRegression", "FaceDetection!<FaceClassificationRegistration>!<FaceClassificationExtraction>+<AgeRegressor>+Discard");  
37 - Globals->abbreviations.insert("FaceQuality", "Open!Cascade(FrontalFace)+ASEFEyes+Affine(64,64,0.25,0.35)+ImageQuality+Cvt(Gray)+DFFS+Discard");  
38 - Globals->abbreviations.insert("MedianFace", "Open!Cascade(FrontalFace)+ASEFEyes+Affine(256,256,0.37,0.45)+Center(Median)"); 34 + Globals->abbreviations.insert("FaceRecognition", "FaceDetection+Expand+<FaceRecognitionRegistration>+Expand+<FaceRecognitionExtraction>+<FaceRecognitionEmbedding>+<FaceRecognitionQuantization>:MatchProbability(ByteL1)");
  35 + Globals->abbreviations.insert("GenderClassification", "FaceDetection+Expand+<FaceClassificationRegistration>+Expand+<FaceClassificationExtraction>+<GenderClassifier>+Discard");
  36 + Globals->abbreviations.insert("AgeRegression", "FaceDetection+Expand+<FaceClassificationRegistration>+Expand+<FaceClassificationExtraction>+<AgeRegressor>+Discard");
  37 + Globals->abbreviations.insert("FaceQuality", "Open+Expand+Cascade(FrontalFace)+ASEFEyes+Affine(64,64,0.25,0.35)+ImageQuality+Cvt(Gray)+DFFS+Discard");
  38 + Globals->abbreviations.insert("MedianFace", "Open+Expand+Cascade(FrontalFace)+ASEFEyes+Affine(256,256,0.37,0.45)+Center(Median)");
39 Globals->abbreviations.insert("BlurredFaceDetection", "Open+LimitSize(1024)+SkinMask/(Cvt(Gray)+GradientMask)+And+Morph(Erode,16)+LargestConvexArea"); 39 Globals->abbreviations.insert("BlurredFaceDetection", "Open+LimitSize(1024)+SkinMask/(Cvt(Gray)+GradientMask)+And+Morph(Erode,16)+LargestConvexArea");
40 - Globals->abbreviations.insert("DrawFaceDetection", "Open+Cascade(FrontalFace)!ASEFEyes+Draw");  
41 - Globals->abbreviations.insert("ShowFaceDetection", "DrawFaceDetection!Show"); 40 + Globals->abbreviations.insert("DrawFaceDetection", "Open+Cascade(FrontalFace)+Expand+ASEFEyes+Draw");
  41 + Globals->abbreviations.insert("ShowFaceDetection", "DrawFaceDetection+Expand+Show");
42 Globals->abbreviations.insert("OpenBR", "FaceRecognition"); 42 Globals->abbreviations.insert("OpenBR", "FaceRecognition");
43 Globals->abbreviations.insert("GenderEstimation", "GenderClassification"); 43 Globals->abbreviations.insert("GenderEstimation", "GenderClassification");
44 Globals->abbreviations.insert("AgeEstimation", "AgeRegression"); 44 Globals->abbreviations.insert("AgeEstimation", "AgeRegression");
@@ -60,7 +60,7 @@ class AlgorithmsInitializer : public Initializer @@ -60,7 +60,7 @@ class AlgorithmsInitializer : public Initializer
60 Globals->abbreviations.insert("SURF", "Open+KeyPointDetector(SURF)+KeyPointDescriptor(SURF):KeyPointMatcher(BruteForce)"); 60 Globals->abbreviations.insert("SURF", "Open+KeyPointDetector(SURF)+KeyPointDescriptor(SURF):KeyPointMatcher(BruteForce)");
61 Globals->abbreviations.insert("SmallSIFT", "Open+LimitSize(512)+KeyPointDetector(SIFT)+KeyPointDescriptor(SIFT):KeyPointMatcher(BruteForce)"); 61 Globals->abbreviations.insert("SmallSIFT", "Open+LimitSize(512)+KeyPointDetector(SIFT)+KeyPointDescriptor(SIFT):KeyPointMatcher(BruteForce)");
62 Globals->abbreviations.insert("SmallSURF", "Open+LimitSize(512)+KeyPointDetector(SURF)+KeyPointDescriptor(SURF):KeyPointMatcher(BruteForce)"); 62 Globals->abbreviations.insert("SmallSURF", "Open+LimitSize(512)+KeyPointDetector(SURF)+KeyPointDescriptor(SURF):KeyPointMatcher(BruteForce)");
63 - Globals->abbreviations.insert("ColorHist", "Open+LimitSize(512)!EnsureChannels(3)+SplitChannels+Hist(256,0,8)+Cat+Normalize(L1):L2"); 63 + Globals->abbreviations.insert("ColorHist", "Open+LimitSize(512)+Expand+EnsureChannels(3)+SplitChannels+Hist(256,0,8)+Cat+Normalize(L1):L2");
64 Globals->abbreviations.insert("ImageClassification", "Open+CropSquare+LimitSize(256)+Cvt(Gray)+Gradient+Bin(0,360,9,true)+Merge+Integral+RecursiveIntegralSampler(4,2,8,Singleton(KMeans(256)))+Cat+CvtFloat+Hist(256)+KNN(5,Dist(L1),false,5)+Rename(KNN,Subject)"); 64 Globals->abbreviations.insert("ImageClassification", "Open+CropSquare+LimitSize(256)+Cvt(Gray)+Gradient+Bin(0,360,9,true)+Merge+Integral+RecursiveIntegralSampler(4,2,8,Singleton(KMeans(256)))+Cat+CvtFloat+Hist(256)+KNN(5,Dist(L1),false,5)+Rename(KNN,Subject)");
65 Globals->abbreviations.insert("TanTriggs", "Blur(1.1)+Gamma(0.2)+DoG(1,2)+ContrastEq(0.1,10)"); 65 Globals->abbreviations.insert("TanTriggs", "Blur(1.1)+Gamma(0.2)+DoG(1,2)+ContrastEq(0.1,10)");
66 66
openbr/plugins/crop.cpp
@@ -57,10 +57,16 @@ BR_REGISTER(Transform, CropTransform) @@ -57,10 +57,16 @@ BR_REGISTER(Transform, CropTransform)
57 class ROITransform : public UntrainableTransform 57 class ROITransform : public UntrainableTransform
58 { 58 {
59 Q_OBJECT 59 Q_OBJECT
  60 + Q_PROPERTY(QString propName READ get_propName WRITE set_propName RESET reset_propName STORED false)
  61 + BR_PROPERTY(QString, propName, "")
60 62
61 void project(const Template &src, Template &dst) const 63 void project(const Template &src, Template &dst) const
62 { 64 {
63 - if (src.file.rects().empty()) { 65 + if (!propName.isEmpty()) {
  66 + QRectF rect = src.file.get<QRectF>(propName);
  67 + dst += src.m()(OpenCVUtils::toRect(rect));
  68 + }
  69 + else if (src.file.rects().empty()) {
64 dst = src; 70 dst = src;
65 if (Globals->verbose) qWarning("No rects present in file."); 71 if (Globals->verbose) qWarning("No rects present in file.");
66 } 72 }
openbr/plugins/draw.cpp
@@ -56,7 +56,7 @@ class DrawTransform : public UntrainableTransform @@ -56,7 +56,7 @@ class DrawTransform : public UntrainableTransform
56 for (int i=0; i<pointsList.size(); i++) { 56 for (int i=0; i<pointsList.size(); i++) {
57 const Point2f &point = pointsList[i]; 57 const Point2f &point = pointsList[i];
58 circle(dst, point, 3, color, -1); 58 circle(dst, point, 3, color, -1);
59 - if (verbose) putText(dst, QString::number(i).toStdString(), point, FONT_HERSHEY_SIMPLEX, 0.5, verboseColor, 1); 59 + if (verbose) putText(dst, QString("%1,(%2,%3)").arg(QString::number(i),QString::number(point.x),QString::number(point.y)).toStdString(), point, FONT_HERSHEY_SIMPLEX, 0.5, verboseColor, 1);
60 } 60 }
61 } 61 }
62 if (rects) { 62 if (rects) {
@@ -336,8 +336,7 @@ class AdjacentOverlayTransform : public Transform @@ -336,8 +336,7 @@ class AdjacentOverlayTransform : public Transform
336 336
337 void init() 337 void init()
338 { 338 {
339 - opener = br::Transform::fromAlgorithm("Cache(Open)");  
340 - 339 + opener = QSharedPointer<br::Transform>(br::Transform::make("Cache(Open)", NULL));
341 } 340 }
342 341
343 }; 342 };
openbr/plugins/gui.cpp
@@ -176,6 +176,10 @@ public: @@ -176,6 +176,10 @@ public:
176 setFixedSize(200,200); 176 setFixedSize(200,200);
177 QApplication::instance()->installEventFilter(this); 177 QApplication::instance()->installEventFilter(this);
178 } 178 }
  179 + ~DisplayWindow()
  180 + {
  181 + QApplication::instance()->removeEventFilter(this);
  182 + }
179 183
180 public slots: 184 public slots:
181 void showImage(const QPixmap & input) 185 void showImage(const QPixmap & input)
@@ -193,7 +197,6 @@ public slots: @@ -193,7 +197,6 @@ public slots:
193 setFixedSize(temp); 197 setFixedSize(temp);
194 } 198 }
195 199
196 -  
197 bool eventFilter(QObject * obj, QEvent * event) 200 bool eventFilter(QObject * obj, QEvent * event)
198 { 201 {
199 if (event->type() == QEvent::KeyPress) 202 if (event->type() == QEvent::KeyPress)
@@ -420,7 +423,10 @@ public: @@ -420,7 +423,10 @@ public:
420 ~ShowTransform() 423 ~ShowTransform()
421 { 424 {
422 delete displayBuffer; 425 delete displayBuffer;
423 - delete window; 426 + if (QThread::currentThread() == QCoreApplication::instance()->thread())
  427 + delete window;
  428 + else
  429 + emit destroyWindow();
424 } 430 }
425 431
426 void train(const TemplateList &data) { (void) data; } 432 void train(const TemplateList &data) { (void) data; }
@@ -494,6 +500,7 @@ public: @@ -494,6 +500,7 @@ public:
494 connect(this, SIGNAL(updateImage(QPixmap)), window,SLOT(showImage(QPixmap))); 500 connect(this, SIGNAL(updateImage(QPixmap)), window,SLOT(showImage(QPixmap)));
495 connect(this, SIGNAL(changeTitle(QString)), window, SLOT(setWindowTitle(QString))); 501 connect(this, SIGNAL(changeTitle(QString)), window, SLOT(setWindowTitle(QString)));
496 connect(this, SIGNAL(hideWindow()), window, SLOT(hide())); 502 connect(this, SIGNAL(hideWindow()), window, SLOT(hide()));
  503 + connect(this, SIGNAL(destroyWindow()), window, SLOT(deleteLater()), Qt::BlockingQueuedConnection);
497 } 504 }
498 505
499 protected: 506 protected:
@@ -506,6 +513,7 @@ signals: @@ -506,6 +513,7 @@ signals:
506 void updateImage(const QPixmap & input); 513 void updateImage(const QPixmap & input);
507 void changeTitle(const QString & input); 514 void changeTitle(const QString & input);
508 void hideWindow(); 515 void hideWindow();
  516 + void destroyWindow();
509 }; 517 };
510 BR_REGISTER(Transform, ShowTransform) 518 BR_REGISTER(Transform, ShowTransform)
511 519
openbr/plugins/landmarks.cpp
@@ -305,6 +305,116 @@ class DrawDelaunayTransform : public UntrainableTransform @@ -305,6 +305,116 @@ class DrawDelaunayTransform : public UntrainableTransform
305 305
306 BR_REGISTER(Transform, DrawDelaunayTransform) 306 BR_REGISTER(Transform, DrawDelaunayTransform)
307 307
  308 +/*!
  309 + * \ingroup transforms
  310 + * \brief Read landmarks from a file and associate them with the correct templates.
  311 + * \author Scott Klum \cite sklum
  312 + *
  313 + * Example of the format:
  314 + * \code
  315 + * image_001.jpg:146.000000,190.000000,227.000000,186.000000,202.000000,256.000000
  316 + * image_002.jpg:75.000000,235.000000,140.000000,225.000000,91.000000,300.000000
  317 + * image_003.jpg:158.000000,186.000000,246.000000,188.000000,208.000000,233.000000
  318 + * \endcode
  319 + */
  320 +class ReadLandmarksTransform : public UntrainableTransform
  321 +{
  322 + Q_OBJECT
  323 +
  324 + Q_PROPERTY(QString file READ get_file WRITE set_file RESET reset_file STORED false)
  325 + Q_PROPERTY(QString imageDelimiter READ get_imageDelimiter WRITE set_imageDelimiter RESET reset_imageDelimiter STORED false)
  326 + Q_PROPERTY(QString landmarkDelimiter READ get_landmarkDelimiter WRITE set_landmarkDelimiter RESET reset_landmarkDelimiter STORED false)
  327 + BR_PROPERTY(QString, file, QString())
  328 + BR_PROPERTY(QString, imageDelimiter, ":")
  329 + BR_PROPERTY(QString, landmarkDelimiter, ",")
  330 +
  331 + QHash<QString, QList<QPointF> > landmarks;
  332 +
  333 + void init()
  334 + {
  335 + if (file.isEmpty())
  336 + return;
  337 +
  338 + QFile f(file);
  339 + if (!f.open(QFile::ReadOnly | QFile::Text))
  340 + qFatal("Failed to open %s for reading.", qPrintable(f.fileName()));
  341 +
  342 + while (!f.atEnd()) {
  343 + const QStringList words = QString(f.readLine()).split(imageDelimiter);
  344 + const QStringList lm = words[1].split(landmarkDelimiter);
  345 +
  346 + QList<QPointF> points;
  347 + bool ok;
  348 + for (int i=0; i<lm.size(); i+=2)
  349 + points.append(QPointF(lm[i].toFloat(&ok),lm[i+1].toFloat(&ok)));
  350 + if (!ok) qFatal("Failed to read landmark.");
  351 +
  352 + landmarks.insert(words[0],points);
  353 + }
  354 + }
  355 +
  356 + void project(const Template &src, Template &dst) const
  357 + {
  358 + dst = src;
  359 +
  360 + dst.file.appendPoints(landmarks[dst.file.fileName()]);
  361 + }
  362 +};
  363 +
  364 +BR_REGISTER(Transform, ReadLandmarksTransform)
  365 +
  366 +/*!
  367 + * \ingroup transforms
  368 + * \brief Name a point
  369 + * \author Scott Klum \cite sklum
  370 + */
  371 +class NamePointsTransform : public UntrainableMetaTransform
  372 +{
  373 + Q_OBJECT
  374 + Q_PROPERTY(QList<int> indices READ get_indices WRITE set_indices RESET reset_indices STORED false)
  375 + Q_PROPERTY(QStringList names READ get_names WRITE set_names RESET reset_names STORED false)
  376 + BR_PROPERTY(QList<int>, indices, QList<int>())
  377 + BR_PROPERTY(QStringList, names, QStringList())
  378 +
  379 + void project(const Template &src, Template &dst) const
  380 + {
  381 + if (indices.size() != names.size()) qFatal("Point/name size mismatch");
  382 +
  383 + dst = src;
  384 +
  385 + QList<QPointF> points = src.file.points();
  386 +
  387 + for (int i=0; i<indices.size(); i++) {
  388 + if (indices[i] < points.size()) dst.file.set(names[i], points[indices[i]]);
  389 + else qFatal("Idex out of range.");
  390 + }
  391 + }
  392 +};
  393 +
  394 +BR_REGISTER(Transform, NamePointsTransform)
  395 +
  396 +/*!
  397 + * \ingroup transforms
  398 + * \brief Remove a name from a point
  399 + * \author Scott Klum \cite sklum
  400 + */
  401 +class AnonymizePointsTransform : public UntrainableMetaTransform
  402 +{
  403 + Q_OBJECT
  404 + Q_PROPERTY(QStringList names READ get_names WRITE set_names RESET reset_names STORED false)
  405 + BR_PROPERTY(QStringList, names, QStringList())
  406 +
  407 + void project(const Template &src, Template &dst) const
  408 + {
  409 + dst = src;
  410 +
  411 + foreach (const QString &name, names)
  412 + if (src.file.contains(name)) dst.file.appendPoint(src.file.get<QPointF>(name));
  413 + }
  414 +};
  415 +
  416 +BR_REGISTER(Transform, AnonymizePointsTransform)
  417 +
308 } // namespace br 418 } // namespace br
309 419
310 #include "landmarks.moc" 420 #include "landmarks.moc"
openbr/plugins/meta.cpp
@@ -248,8 +248,8 @@ class ExpandTransform : public UntrainableMetaTransform @@ -248,8 +248,8 @@ class ExpandTransform : public UntrainableMetaTransform
248 248
249 virtual void project(const Template & src, Template & dst) const 249 virtual void project(const Template & src, Template & dst) const
250 { 250 {
251 - qFatal("this has gone bad");  
252 - (void) src; (void) dst; 251 + dst = src;
  252 + qDebug("Called Expand project(Template,Template), nothing will happen");
253 } 253 }
254 }; 254 };
255 255
@@ -614,13 +614,20 @@ class DistributeTemplateTransform : public MetaTransform @@ -614,13 +614,20 @@ class DistributeTemplateTransform : public MetaTransform
614 614
615 public: 615 public:
616 616
617 - Transform * smartCopy() 617 + Transform * smartCopy(bool & newTransform)
618 { 618 {
619 - if (!transform->timeVarying()) 619 + if (!transform->timeVarying()) {
  620 + newTransform = false;
620 return this; 621 return this;
  622 + }
  623 + newTransform = true;
621 624
622 DistributeTemplateTransform * output = new DistributeTemplateTransform; 625 DistributeTemplateTransform * output = new DistributeTemplateTransform;
623 - output->transform = transform->smartCopy(); 626 + bool newChild = false;
  627 + output->transform = transform->smartCopy(newChild);
  628 + if (newChild)
  629 + output->transform->setParent(output);
  630 +
624 return output; 631 return output;
625 } 632 }
626 633
openbr/plugins/openbr_internal.h
@@ -139,8 +139,9 @@ public: @@ -139,8 +139,9 @@ public:
139 *\brief For transforms that don't do any training, this default implementation 139 *\brief For transforms that don't do any training, this default implementation
140 * which creates a new copy of the Transform from its description string is sufficient. 140 * which creates a new copy of the Transform from its description string is sufficient.
141 */ 141 */
142 - virtual Transform * smartCopy() 142 + virtual Transform * smartCopy(bool & newTransform)
143 { 143 {
  144 + newTransform = true;
144 return this->clone(); 145 return this->clone();
145 } 146 }
146 147
@@ -250,10 +251,13 @@ public: @@ -250,10 +251,13 @@ public:
250 * it creates a new copy of its own class, and gives that copy the child transforms 251 * it creates a new copy of its own class, and gives that copy the child transforms
251 * returned by calling smartCopy on this transforms children 252 * returned by calling smartCopy on this transforms children
252 */ 253 */
253 - Transform * smartCopy() 254 + Transform * smartCopy(bool & newTransform)
254 { 255 {
255 - if (!timeVarying()) 256 + if (!timeVarying()) {
  257 + newTransform = false;
256 return this; 258 return this;
  259 + }
  260 + newTransform = true;
257 261
258 QString name = metaObject()->className(); 262 QString name = metaObject()->className();
259 name.replace("Transform",""); 263 name.replace("Transform","");
@@ -266,8 +270,9 @@ public: @@ -266,8 +270,9 @@ public:
266 270
267 foreach(Transform* t, transforms ) 271 foreach(Transform* t, transforms )
268 { 272 {
269 - Transform * maybe_copy = t->smartCopy();  
270 - if (maybe_copy->parent() == NULL) 273 + bool newItem = false;
  274 + Transform * maybe_copy = t->smartCopy(newItem);
  275 + if (newItem)
271 maybe_copy->setParent(output); 276 maybe_copy->setParent(output);
272 output->transforms.append(maybe_copy); 277 output->transforms.append(maybe_copy);
273 } 278 }
openbr/plugins/slidingwindow.cpp
@@ -380,8 +380,10 @@ private: @@ -380,8 +380,10 @@ private:
380 QList<Rect> rects; 380 QList<Rect> rects;
381 QList<float> confidences; 381 QList<float> confidences;
382 foreach (const Template &t, src) { 382 foreach (const Template &t, src) {
383 - rects.append(OpenCVUtils::toRect(t.file.get<QRectF>("Detection")));  
384 - confidences.append(t.file.get<float>("Confidence")); 383 + if (t.file.contains("Detection")) {
  384 + rects.append(OpenCVUtils::toRect(t.file.get<QRectF>("Detection")));
  385 + confidences.append(t.file.get<float>("Confidence"));
  386 + }
385 } 387 }
386 388
387 // Compute overlap between rectangles and create discrete Laplacian matrix 389 // Compute overlap between rectangles and create discrete Laplacian matrix
openbr/plugins/stream.cpp
@@ -1007,14 +1007,24 @@ public: @@ -1007,14 +1007,24 @@ public:
1007 1007
1008 void project(const Template &src, Template &dst) const 1008 void project(const Template &src, Template &dst) const
1009 { 1009 {
1010 - (void) src; (void) dst;  
1011 - qFatal("nope"); 1010 + TemplateList in;
  1011 + in.append(src);
  1012 + TemplateList out;
  1013 + CompositeTransform::project(in,out);
  1014 + dst = out.first();
  1015 + if (out.size() > 1)
  1016 + qDebug("Returning first output template only");
1012 } 1017 }
1013 1018
1014 void projectUpdate(const Template &src, Template &dst) 1019 void projectUpdate(const Template &src, Template &dst)
1015 { 1020 {
1016 - (void) src; (void) dst;  
1017 - qFatal("whatever"); 1021 + TemplateList in;
  1022 + in.append(src);
  1023 + TemplateList out;
  1024 + projectUpdate(in,out);
  1025 + dst = out.first();
  1026 + if (out.size() > 1)
  1027 + qDebug("Returning first output template only");
1018 } 1028 }
1019 1029
1020 1030
@@ -1082,10 +1092,6 @@ public: @@ -1082,10 +1092,6 @@ public:
1082 1092
1083 // dst is set to all output received by the final stage, along 1093 // dst is set to all output received by the final stage, along
1084 // with anything output via the calls to finalize. 1094 // with anything output via the calls to finalize.
1085 - //dst = collectionStage->getOutput();  
1086 -  
1087 - // dst is set to all output received by the final stage, along  
1088 - // with anything output via the calls to finalize.  
1089 foreach(const TemplateList & list, collector->sets) { 1095 foreach(const TemplateList & list, collector->sets) {
1090 dst.append(list); 1096 dst.append(list);
1091 } 1097 }
@@ -1368,10 +1374,10 @@ public: @@ -1368,10 +1374,10 @@ public:
1368 basis.init(); 1374 basis.init();
1369 } 1375 }
1370 1376
1371 - Transform * smartCopy() 1377 + Transform * smartCopy(bool & newTransform)
1372 { 1378 {
1373 // We just want the DirectStream to begin with, so just return a copy of that. 1379 // We just want the DirectStream to begin with, so just return a copy of that.
1374 - DirectStreamTransform * res = (DirectStreamTransform *) basis.smartCopy(); 1380 + DirectStreamTransform * res = (DirectStreamTransform *) basis.smartCopy(newTransform);
1375 res->activeFrames = this->activeFrames; 1381 res->activeFrames = this->activeFrames;
1376 return res; 1382 return res;
1377 } 1383 }
openbr/plugins/template.cpp
@@ -50,58 +50,6 @@ class RemoveTemplatesTransform : public UntrainableMetaTransform @@ -50,58 +50,6 @@ class RemoveTemplatesTransform : public UntrainableMetaTransform
50 50
51 BR_REGISTER(Transform, RemoveTemplatesTransform) 51 BR_REGISTER(Transform, RemoveTemplatesTransform)
52 52
53 -/*!  
54 - * \ingroup transforms  
55 - * \brief Name a point  
56 - * \author Scott Klum \cite sklum  
57 - */  
58 -class NamePointsTransform : public UntrainableMetaTransform  
59 -{  
60 - Q_OBJECT  
61 - Q_PROPERTY(QList<int> indices READ get_indices WRITE set_indices RESET reset_indices STORED false)  
62 - Q_PROPERTY(QStringList names READ get_names WRITE set_names RESET reset_names STORED false)  
63 - BR_PROPERTY(QList<int>, indices, QList<int>())  
64 - BR_PROPERTY(QStringList, names, QStringList())  
65 -  
66 - void project(const Template &src, Template &dst) const  
67 - {  
68 - if (indices.size() != names.size()) qFatal("Point/name size mismatch");  
69 -  
70 - dst = src;  
71 -  
72 - QList<QPointF> points = src.file.points();  
73 -  
74 - for (int i=0; i<indices.size(); i++) {  
75 - if (indices[i] < points.size()) dst.file.set(names[i], points[indices[i]]);  
76 - else qFatal("Idex out of range.");  
77 - }  
78 - }  
79 -};  
80 -  
81 -BR_REGISTER(Transform, NamePointsTransform)  
82 -  
83 -/*!  
84 - * \ingroup transforms  
85 - * \brief Remove a name from a point  
86 - * \author Scott Klum \cite sklum  
87 - */  
88 -class AnonymizePointsTransform : public UntrainableMetaTransform  
89 -{  
90 - Q_OBJECT  
91 - Q_PROPERTY(QStringList names READ get_names WRITE set_names RESET reset_names STORED false)  
92 - BR_PROPERTY(QStringList, names, QStringList())  
93 -  
94 - void project(const Template &src, Template &dst) const  
95 - {  
96 - dst = src;  
97 -  
98 - foreach (const QString &name, names)  
99 - if (src.file.contains(name)) dst.file.appendPoint(src.file.get<QPointF>(name));  
100 - }  
101 -};  
102 -  
103 -BR_REGISTER(Transform, AnonymizePointsTransform)  
104 -  
105 } // namespace br 53 } // namespace br
106 54
107 #include "template.moc" 55 #include "template.moc"
scripts/evalFaceRecognition-LFW.sh 0 → 100755
  1 +#!/bin/bash
  2 +
  3 +ALGORITHM=FaceRecognition
  4 +
  5 +if [ ! -f evalFaceRecognition-LFW.sh ]; then
  6 + echo "Run this script from the scripts folder!"
  7 + exit
  8 +fi
  9 +
  10 +if ! hash br 2>/dev/null; then
  11 + echo "Can't find 'br'. Did you forget to build and install OpenBR? Here's some help: http://openbiometrics.org/doxygen/latest/installation.html"
  12 + exit
  13 +fi
  14 +
  15 +# Get the data
  16 +./downloadDatasets.sh
  17 +
  18 +if [ ! -e Algorithm_Dataset ]; then
  19 + mkdir Algorithm_Dataset
  20 +fi
  21 +
  22 +# Run the LFW test protocol
  23 +br -useGui 0 -algorithm $ALGORITHM -path ../data/LFW/img/ -crossValidate 10 -pairwiseCompare ../data/LFW/sigset/test_image_restricted_target.xml ../data/LFW/sigset/test_image_restricted_query.xml ${ALGORITHM}_LFW.mtx -convert Output ${ALGORITHM}_lfw.mtx Algorithm_Dataset/${ALGORITHM}_LFW%1.eval
  24 +
  25 +# Plot results
  26 +br -useGui 0 -plot Algorithm_Dataset/* 'lfw_results.pdf[smooth=Dataset,rocOptions[yLimits=(0,1)]]'
scripts/evalGenderClassification-PCSO.sh
@@ -5,12 +5,11 @@ if [ ! -f evalGenderClassification-PCSO.sh ]; then @@ -5,12 +5,11 @@ if [ ! -f evalGenderClassification-PCSO.sh ]; then
5 fi 5 fi
6 6
7 export BR=../build/app/br/br 7 export BR=../build/app/br/br
8 -export genderAlg=GenderClassification  
9 -  
10 -export PCSO_DIR=/user/pripshare/Databases/FaceDatabases/PCSO/PCSO/ 8 +export ALGORITHM=GenderClassification
  9 +export PCSO_DIR=../data/PCSO/img
11 10
12 # Create a file list by querying the database 11 # Create a file list by querying the database
13 $BR -useGui 0 -quiet -algorithm Identity -enroll "$PCSO_DIR/PCSO.db[query='SELECT File,Gender,PersonID FROM PCSO', subset=1:8000]" terminal.txt > Input.txt 12 $BR -useGui 0 -quiet -algorithm Identity -enroll "$PCSO_DIR/PCSO.db[query='SELECT File,Gender,PersonID FROM PCSO', subset=1:8000]" terminal.txt > Input.txt
14 13
15 # Enroll the file list and evaluate performance 14 # Enroll the file list and evaluate performance
16 -$BR -useGui 0 -algorithm $genderAlg -path $PCSO_DIR/Images -enroll Input.txt Output.txt -evalClassification Output.txt Input.txt Gender  
17 \ No newline at end of file 15 \ No newline at end of file
  16 +$BR -useGui 0 -algorithm $ALGORITHM -path $PCSO_DIR -enroll Input.txt Output.txt -evalClassification Output.txt Input.txt Gender
18 \ No newline at end of file 17 \ No newline at end of file
1 -Subproject commit a73d51013ea05f263e88a28539393159fff2183e 1 +Subproject commit bcbff8c485f19daddb2e6b2abd5a505ed8c1e526