Commit 2f4fffeddbecab9edc57f096318c3655b2e047d5

Authored by Scott Klum
2 parents e335e0ce fea31bb9

Merge branch 'master' of https://github.com/biometrics/openbr

.gitignore
... ... @@ -4,6 +4,7 @@
4 4 data/*/img
5 5 data/*/vid
6 6 data/PCSO/*
  7 +data/lfpw
7 8 build*
8 9 scripts/results
9 10  
... ... @@ -38,3 +39,4 @@ scripts/results
38 39 ### autogenerated sigsets ###
39 40 data/INRIAPerson/sigset
40 41 data/KTH/sigset
  42 +
... ...
openbr/core/core.cpp
... ... @@ -70,7 +70,7 @@ struct AlgorithmCore
70 70  
71 71 if (!distance.isNull()) {
72 72 qDebug("Projecting Enrollment");
73   - data >> *transform;
  73 + data >> *downcast;
74 74  
75 75 qDebug("Training Comparison");
76 76 distance->train(data);
... ...
openbr/openbr.cpp
... ... @@ -341,6 +341,12 @@ int br_img_channels(br_template tmpl)
341 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 350 void br_set_filename(br_template tmpl, const char *filename)
345 351 {
346 352 Template *t = reinterpret_cast<Template*>(tmpl);
... ... @@ -356,6 +362,12 @@ br_template_list br_enroll_template(br_template tmpl)
356 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 371 br_template br_get_template(br_template_list tl, int index)
360 372 {
361 373 TemplateList *realTL = reinterpret_cast<TemplateList*>(tl);
... ...
openbr/openbr.h
... ... @@ -467,6 +467,10 @@ BR_EXPORT int br_img_cols(br_template tmpl);
467 467 */
468 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 474 * \brief Set the filename for a template.
471 475 */
472 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 480 */
477 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 488 * \brief Get a pointer to a br::Template at a specified index.
480 489 * \param tl Pointer to a br::TemplateList.
481 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 1184 if (Globals->abbreviations.contains(str))
1185 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 1187 //! [Make a pipe]
1192 1188 { // Check for use of '+' as shorthand for Pipe(...)
1193 1189 QStringList words = parse(str, '+');
... ...
openbr/openbr_plugin.h
... ... @@ -1209,7 +1209,9 @@ public:
1209 1209 * and copy enough of their state that projectUpdate can safely be called on the original
1210 1210 * instance, and the copy concurrently.
1211 1211 */
1212   - 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);}
1213 1215  
1214 1216 /*!
1215 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 31 void initialize() const
32 32 {
33 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 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 42 Globals->abbreviations.insert("OpenBR", "FaceRecognition");
43 43 Globals->abbreviations.insert("GenderEstimation", "GenderClassification");
44 44 Globals->abbreviations.insert("AgeEstimation", "AgeRegression");
... ... @@ -60,7 +60,7 @@ class AlgorithmsInitializer : public Initializer
60 60 Globals->abbreviations.insert("SURF", "Open+KeyPointDetector(SURF)+KeyPointDescriptor(SURF):KeyPointMatcher(BruteForce)");
61 61 Globals->abbreviations.insert("SmallSIFT", "Open+LimitSize(512)+KeyPointDetector(SIFT)+KeyPointDescriptor(SIFT):KeyPointMatcher(BruteForce)");
62 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 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 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 57 class ROITransform : public UntrainableTransform
58 58 {
59 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 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 70 dst = src;
65 71 if (Globals->verbose) qWarning("No rects present in file.");
66 72 }
... ...
openbr/plugins/gui.cpp
... ... @@ -176,6 +176,10 @@ public:
176 176 setFixedSize(200,200);
177 177 QApplication::instance()->installEventFilter(this);
178 178 }
  179 + ~DisplayWindow()
  180 + {
  181 + QApplication::instance()->removeEventFilter(this);
  182 + }
179 183  
180 184 public slots:
181 185 void showImage(const QPixmap & input)
... ... @@ -193,7 +197,6 @@ public slots:
193 197 setFixedSize(temp);
194 198 }
195 199  
196   -
197 200 bool eventFilter(QObject * obj, QEvent * event)
198 201 {
199 202 if (event->type() == QEvent::KeyPress)
... ... @@ -420,7 +423,10 @@ public:
420 423 ~ShowTransform()
421 424 {
422 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 432 void train(const TemplateList &data) { (void) data; }
... ... @@ -494,6 +500,7 @@ public:
494 500 connect(this, SIGNAL(updateImage(QPixmap)), window,SLOT(showImage(QPixmap)));
495 501 connect(this, SIGNAL(changeTitle(QString)), window, SLOT(setWindowTitle(QString)));
496 502 connect(this, SIGNAL(hideWindow()), window, SLOT(hide()));
  503 + connect(this, SIGNAL(destroyWindow()), window, SLOT(deleteLater()), Qt::BlockingQueuedConnection);
497 504 }
498 505  
499 506 protected:
... ... @@ -506,6 +513,7 @@ signals:
506 513 void updateImage(const QPixmap & input);
507 514 void changeTitle(const QString & input);
508 515 void hideWindow();
  516 + void destroyWindow();
509 517 };
510 518 BR_REGISTER(Transform, ShowTransform)
511 519  
... ...
openbr/plugins/landmarks.cpp
... ... @@ -332,6 +332,9 @@ class ReadLandmarksTransform : public UntrainableTransform
332 332  
333 333 void init()
334 334 {
  335 + if (file.isEmpty())
  336 + return;
  337 +
335 338 QFile f(file);
336 339 if (!f.open(QFile::ReadOnly | QFile::Text))
337 340 qFatal("Failed to open %s for reading.", qPrintable(f.fileName()));
... ...
openbr/plugins/meta.cpp
... ... @@ -614,13 +614,20 @@ class DistributeTemplateTransform : public MetaTransform
614 614  
615 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 621 return this;
  622 + }
  623 + newTransform = true;
621 624  
622 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 631 return output;
625 632 }
626 633  
... ...
openbr/plugins/openbr_internal.h
... ... @@ -139,8 +139,9 @@ public:
139 139 *\brief For transforms that don't do any training, this default implementation
140 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 145 return this->clone();
145 146 }
146 147  
... ... @@ -250,10 +251,13 @@ public:
250 251 * it creates a new copy of its own class, and gives that copy the child transforms
251 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 258 return this;
  259 + }
  260 + newTransform = true;
257 261  
258 262 QString name = metaObject()->className();
259 263 name.replace("Transform","");
... ... @@ -266,8 +270,9 @@ public:
266 270  
267 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 276 maybe_copy->setParent(output);
272 277 output->transforms.append(maybe_copy);
273 278 }
... ...
openbr/plugins/slidingwindow.cpp
... ... @@ -380,8 +380,10 @@ private:
380 380 QList<Rect> rects;
381 381 QList<float> confidences;
382 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 389 // Compute overlap between rectangles and create discrete Laplacian matrix
... ...
openbr/plugins/stream.cpp
... ... @@ -1092,10 +1092,6 @@ public:
1092 1092  
1093 1093 // dst is set to all output received by the final stage, along
1094 1094 // with anything output via the calls to finalize.
1095   - //dst = collectionStage->getOutput();
1096   -
1097   - // dst is set to all output received by the final stage, along
1098   - // with anything output via the calls to finalize.
1099 1095 foreach(const TemplateList & list, collector->sets) {
1100 1096 dst.append(list);
1101 1097 }
... ... @@ -1378,10 +1374,10 @@ public:
1378 1374 basis.init();
1379 1375 }
1380 1376  
1381   - Transform * smartCopy()
  1377 + Transform * smartCopy(bool & newTransform)
1382 1378 {
1383 1379 // We just want the DirectStream to begin with, so just return a copy of that.
1384   - DirectStreamTransform * res = (DirectStreamTransform *) basis.smartCopy();
  1380 + DirectStreamTransform * res = (DirectStreamTransform *) basis.smartCopy(newTransform);
1385 1381 res->activeFrames = this->activeFrames;
1386 1382 return res;
1387 1383 }
... ...
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 5 fi
6 6  
7 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 11 # Create a file list by querying the database
13 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 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 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 17 \ No newline at end of file
... ...
1   -Subproject commit a73d51013ea05f263e88a28539393159fff2183e
  1 +Subproject commit bcbff8c485f19daddb2e6b2abd5a505ed8c1e526
... ...