Commit c2634f0f043353582755dcc3889ac15da0210e76
Merge branch 'master' into janus
Showing
19 changed files
with
249 additions
and
102 deletions
.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 |