Commit cdb6b4fb4004e23c7e759d28efe1373576d4a180

Authored by caotto
2 parents 7c9ace46 a438d3fa

Merge pull request #213 from biometrics/inline_pp5

Refactor PP5 comparison handling
openbr/core/core.cpp
@@ -27,6 +27,7 @@ struct AlgorithmCore @@ -27,6 +27,7 @@ struct AlgorithmCore
27 { 27 {
28 QSharedPointer<Transform> transform; 28 QSharedPointer<Transform> transform;
29 QSharedPointer<Distance> distance; 29 QSharedPointer<Distance> distance;
  30 + QString galleryCompareString;
30 31
31 QString transformString; 32 QString transformString;
32 QString distanceString; 33 QString distanceString;
@@ -147,9 +148,6 @@ struct AlgorithmCore @@ -147,9 +148,6 @@ struct AlgorithmCore
147 Gallery *temp = Gallery::make(input); 148 Gallery *temp = Gallery::make(input);
148 qint64 total = temp->totalSize(); 149 qint64 total = temp->totalSize();
149 150
150 - Globals->currentStep = 0;  
151 - Globals->totalSteps = total;  
152 -  
153 QScopedPointer<Transform> basePipe; 151 QScopedPointer<Transform> basePipe;
154 152
155 QString pipeDesc = "GalleryOutput("+gallery.flat()+")+ProgressCounter("+QString::number(total)+")+Discard"; 153 QString pipeDesc = "GalleryOutput("+gallery.flat()+")+ProgressCounter("+QString::number(total)+")+Discard";
@@ -189,6 +187,8 @@ struct AlgorithmCore @@ -189,6 +187,8 @@ struct AlgorithmCore
189 wrapper->init(); 187 wrapper->init();
190 188
191 Globals->startTime.start(); 189 Globals->startTime.start();
  190 + Globals->currentStep = 0;
  191 + Globals->totalSteps = total;
192 192
193 TemplateList data, output; 193 TemplateList data, output;
194 data.append(input); 194 data.append(input);
@@ -335,7 +335,7 @@ struct AlgorithmCore @@ -335,7 +335,7 @@ struct AlgorithmCore
335 output.isNull() ? "" : qPrintable(" to " + output.flat())); 335 output.isNull() ? "" : qPrintable(" to " + output.flat()));
336 336
337 // Escape hatch for distances that need to operate directly on the gallery files 337 // Escape hatch for distances that need to operate directly on the gallery files
338 - if (distance->compare(targetGallery, queryGallery, output)) 338 + if (distance && distance->compare(targetGallery, queryGallery, output))
339 return; 339 return;
340 340
341 // Are we comparing the same gallery against itself? 341 // Are we comparing the same gallery against itself?
@@ -442,8 +442,11 @@ struct AlgorithmCore @@ -442,8 +442,11 @@ struct AlgorithmCore
442 // The actual comparison step is done by a GalleryCompare transform, which has a Distance, and a gallery as data. 442 // The actual comparison step is done by a GalleryCompare transform, which has a Distance, and a gallery as data.
443 // Incoming templates are compared against the templates in the gallery, and the output is the resulting score 443 // Incoming templates are compared against the templates in the gallery, and the output is the resulting score
444 // vector. 444 // vector.
445 - QString compareRegionDesc = "Pipe([GalleryCompare("+Globals->algorithm + "," + colEnrolledGallery.flat() + ")])";  
446 - 445 + QString compareRegionDesc;
  446 + if (this->galleryCompareString.isEmpty() )
  447 + compareRegionDesc = "Pipe([GalleryCompare("+Globals->algorithm + "," + colEnrolledGallery.flat() + ")])";
  448 + else
  449 + compareRegionDesc = "Pipe(["+this->galleryCompareString+"("+Globals->algorithm + "," + colEnrolledGallery.flat() + ")])";
447 450
448 QScopedPointer<Transform> compareRegion; 451 QScopedPointer<Transform> compareRegion;
449 // If we need to enroll the row set, we add the current algorithm's enrollment transform before the 452 // If we need to enroll the row set, we add the current algorithm's enrollment transform before the
@@ -519,6 +522,7 @@ struct AlgorithmCore @@ -519,6 +522,7 @@ struct AlgorithmCore
519 522
520 // Set up progress counting variables 523 // Set up progress counting variables
521 Globals->currentStep = 0; 524 Globals->currentStep = 0;
  525 + Globals->currentProgress = 0;
522 Globals->totalSteps = rowSize; 526 Globals->totalSteps = rowSize;
523 Globals->startTime.start(); 527 Globals->startTime.start();
524 528
@@ -553,19 +557,27 @@ private: @@ -553,19 +557,27 @@ private:
553 if (Globals->abbreviations.contains(description)) 557 if (Globals->abbreviations.contains(description))
554 return init(Globals->abbreviations[description]); 558 return init(Globals->abbreviations[description]);
555 559
556 - //! [Parsing the algorithm description]  
557 - QStringList words = QtUtils::parse(description, ':'); 560 + const bool compareTransform = description.contains('!');
  561 + QStringList words = QtUtils::parse(description, compareTransform ? '!' : ':');
  562 +
558 if ((words.size() < 1) || (words.size() > 2)) qFatal("Invalid algorithm format."); 563 if ((words.size() < 1) || (words.size() > 2)) qFatal("Invalid algorithm format.");
559 - //! [Parsing the algorithm description]  
560 564
  565 + //! [Parsing the algorithm description]
561 transformString = words[0]; 566 transformString = words[0];
562 567
563 -  
564 //! [Creating the template generation and comparison methods] 568 //! [Creating the template generation and comparison methods]
565 transform = QSharedPointer<Transform>(Transform::make(words[0], NULL)); 569 transform = QSharedPointer<Transform>(Transform::make(words[0], NULL));
566 if (words.size() > 1) { 570 if (words.size() > 1) {
567 - distance = QSharedPointer<Distance>(Distance::make(words[1], NULL));  
568 - distanceString = words[1]; 571 + if (!compareTransform) {
  572 + distance = QSharedPointer<Distance>(Distance::make(words[1], NULL));
  573 + distanceString = words[1];
  574 + galleryCompareString.clear();
  575 + }
  576 + else {
  577 + galleryCompareString = words[1];
  578 + distanceString.clear();
  579 + }
  580 +
569 } 581 }
570 //! [Creating the template generation and comparison methods] 582 //! [Creating the template generation and comparison methods]
571 } 583 }
openbr/openbr_plugin.cpp
@@ -875,7 +875,7 @@ void br::Context::printStatus() @@ -875,7 +875,7 @@ void br::Context::printStatus()
875 const float p = progress(); 875 const float p = progress();
876 if (p < 1) { 876 if (p < 1) {
877 int s = timeRemaining(); 877 int s = timeRemaining();
878 - fprintf(stderr,"%05.2f%% ELAPSED=%s REMAINING=%s COUNT=%g \r", p*100, QtUtils::toTime(Globals->startTime.elapsed()/1000.0f).toStdString().c_str(), QtUtils::toTime(s).toStdString().c_str(), Globals->currentStep); 878 + fprintf(stderr,"\r%05.2f%% ELAPSED=%s REMAINING=%s COUNT=%g", p*100, QtUtils::toTime(Globals->startTime.elapsed()/1000.0f).toStdString().c_str(), QtUtils::toTime(s).toStdString().c_str(), Globals->currentStep);
879 fflush(stderr); 879 fflush(stderr);
880 } 880 }
881 } 881 }
openbr/plugins/gallery.cpp
@@ -129,7 +129,7 @@ class BinaryGallery : public Gallery @@ -129,7 +129,7 @@ class BinaryGallery : public Gallery
129 if (t.isEmpty() && t.file.isNull()) 129 if (t.isEmpty() && t.file.isNull())
130 continue; 130 continue;
131 templates.append(t); 131 templates.append(t);
132 - templates.last().file.set("progress", totalSize()); 132 + templates.last().file.set("progress", position());
133 133
134 // Special case for pipes where we want to process data as soon as it is available 134 // Special case for pipes where we want to process data as soon as it is available
135 if (gallery.isSequential()) 135 if (gallery.isSequential())
openbr/plugins/misc.cpp
@@ -625,11 +625,18 @@ class ProgressCounterTransform : public TimeVaryingTransform @@ -625,11 +625,18 @@ class ProgressCounterTransform : public TimeVaryingTransform
625 dst = src; 625 dst = src;
626 626
627 qint64 elapsed = timer.elapsed(); 627 qint64 elapsed = timer.elapsed();
628 - 628 + int last_frame = -2;
629 if (!dst.empty()) { 629 if (!dst.empty()) {
630 - Globals->currentProgress = dst.last().file.get<qint64>("progress",0);  
631 - dst.last().file.remove("progress");  
632 - Globals->currentStep++; 630 + for (int i=0;i < dst.size();i++) {
  631 + int frame = dst[i].file.get<int>("FrameNumber", -1);
  632 + if (frame == last_frame)
  633 + continue;
  634 +
  635 + Globals->currentProgress = dst[i].file.get<qint64>("progress",0);
  636 + dst[i].file.remove("progress");
  637 + Globals->currentStep++;
  638 + last_frame = frame;
  639 + }
633 } 640 }
634 641
635 // updated every second 642 // updated every second
@@ -650,13 +657,17 @@ class ProgressCounterTransform : public TimeVaryingTransform @@ -650,13 +657,17 @@ class ProgressCounterTransform : public TimeVaryingTransform
650 { 657 {
651 (void) data; 658 (void) data;
652 float p = br_progress(); 659 float p = br_progress();
653 - qDebug("%05.2f%% ELAPSED=%s REMAINING=%s COUNT=%g \r", p*100, QtUtils::toTime(Globals->startTime.elapsed()/1000.0f).toStdString().c_str(), QtUtils::toTime(0).toStdString().c_str(), Globals->currentStep); 660 + qDebug("\r%05.2f%% ELAPSED=%s REMAINING=%s COUNT=%g", p*100, QtUtils::toTime(Globals->startTime.elapsed()/1000.0f).toStdString().c_str(), QtUtils::toTime(0).toStdString().c_str(), Globals->currentStep);
  661 + Globals->currentStep = 0;
  662 + Globals->currentProgress = 0;
  663 + Globals->totalSteps = 0;
654 } 664 }
655 665
656 void init() 666 void init()
657 { 667 {
658 timer.start(); 668 timer.start();
659 Globals->currentStep = 0; 669 Globals->currentStep = 0;
  670 + Globals->currentProgress = 0;
660 } 671 }
661 672
662 public: 673 public:
@@ -713,26 +724,26 @@ class OutputTransform : public TimeVaryingTransform @@ -713,26 +724,26 @@ class OutputTransform : public TimeVaryingTransform
713 currentCol++; 724 currentCol++;
714 currentRow = 0; 725 currentRow = 0;
715 } 726 }
716 - }  
717 727
718 - bool blockDone = false;  
719 - // In direct mode, we don't buffer rows  
720 - if (!transposeMode) {  
721 - currentBlockRow++;  
722 - blockDone = true;  
723 - }  
724 - // in transpose mode, we buffer 100 cols before writing the block  
725 - else if (currentCol == bufferedSize) {  
726 - currentBlockCol++;  
727 - blockDone = true;  
728 - }  
729 - else return; 728 + bool blockDone = false;
  729 + // In direct mode, we don't buffer rows
  730 + if (!transposeMode) {
  731 + currentBlockRow++;
  732 + blockDone = true;
  733 + }
  734 + // in transpose mode, we buffer 100 cols before writing the block
  735 + else if (currentCol == bufferedSize) {
  736 + currentBlockCol++;
  737 + blockDone = true;
  738 + }
  739 + else return;
730 740
731 - if (blockDone) {  
732 - // set the next block, only necessary if we haven't buffered the current item  
733 - output->setBlock(currentBlockRow, currentBlockCol);  
734 - currentRow = 0;  
735 - currentCol = 0; 741 + if (blockDone) {
  742 + // set the next block, only necessary if we haven't buffered the current item
  743 + output->setBlock(currentBlockRow, currentBlockCol);
  744 + currentRow = 0;
  745 + currentCol = 0;
  746 + }
736 } 747 }
737 } 748 }
738 749
openbr/plugins/pp5.cpp
@@ -45,7 +45,7 @@ class PP5Initializer : public Initializer @@ -45,7 +45,7 @@ class PP5Initializer : public Initializer
45 void initialize() const 45 void initialize() const
46 { 46 {
47 TRY(ppr_initialize_sdk(qPrintable(Globals->sdkPath + "/share/openbr/models/pp5/"), my_license_id, my_license_key)) 47 TRY(ppr_initialize_sdk(qPrintable(Globals->sdkPath + "/share/openbr/models/pp5/"), my_license_id, my_license_key))
48 - Globals->abbreviations.insert("PP5","Open+Expand+PP5Enroll:PP5Compare"); 48 + Globals->abbreviations.insert("PP5","Open+Expand+PP5Enroll!PP5Gallery");
49 Globals->abbreviations.insert("PP5Register", "Open+PP5Enroll(true)+RenameFirst([eyeL,PP5_Landmark0_Right_Eye],Affine_0)+RenameFirst([eyeR,PP5_Landmark1_Left_Eye],Affine_1)"); 49 Globals->abbreviations.insert("PP5Register", "Open+PP5Enroll(true)+RenameFirst([eyeL,PP5_Landmark0_Right_Eye],Affine_0)+RenameFirst([eyeR,PP5_Landmark1_Left_Eye],Affine_1)");
50 Globals->abbreviations.insert("PP5CropFace", "Open+PP5Enroll(true)+RenameFirst([eyeL,PP5_Landmark0_Right_Eye],Affine_0)+RenameFirst([eyeR,PP5_Landmark1_Left_Eye],Affine_1)+Affine(128,128,0.25,0.35)+Cvt(Gray)"); 50 Globals->abbreviations.insert("PP5CropFace", "Open+PP5Enroll(true)+RenameFirst([eyeL,PP5_Landmark0_Right_Eye],Affine_0)+RenameFirst([eyeR,PP5_Landmark1_Left_Eye],Affine_1)+Affine(128,128,0.25,0.35)+Cvt(Gray)");
51 } 51 }
@@ -85,7 +85,7 @@ struct PP5Context @@ -85,7 +85,7 @@ struct PP5Context
85 default_settings.recognition.automatically_extract_templates = 1; 85 default_settings.recognition.automatically_extract_templates = 1;
86 default_settings.recognition.enable_comparison = 1; 86 default_settings.recognition.enable_comparison = 1;
87 default_settings.recognition.enable_extraction = 1; 87 default_settings.recognition.enable_extraction = 1;
88 - default_settings.recognition.num_comparison_threads = QThreadPool::globalInstance()->maxThreadCount(); 88 + default_settings.recognition.num_comparison_threads = 1;
89 default_settings.recognition.recognizer = PPR_RECOGNIZER_MULTI_POSE; 89 default_settings.recognition.recognizer = PPR_RECOGNIZER_MULTI_POSE;
90 TRY(ppr_initialize_context(default_settings, &context)) 90 TRY(ppr_initialize_context(default_settings, &context))
91 } 91 }
@@ -205,6 +205,45 @@ struct PP5Context @@ -205,6 +205,45 @@ struct PP5Context
205 205
206 return metadata; 206 return metadata;
207 } 207 }
  208 +
  209 + void compareNative(ppr_gallery_type target, const QList<int> &targetIDs, ppr_gallery_type query, const QList<int> &queryIDs, Output *output) const
  210 + {
  211 + ppr_similarity_matrix_type simmat;
  212 + TRY(ppr_compare_galleries(context, query, target, &simmat))
  213 + for (int i=0; i<queryIDs.size(); i++) {
  214 + int query_subject_id = queryIDs[i];
  215 + for (int j=0; j<targetIDs.size(); j++) {
  216 + int target_subject_id = targetIDs[j];
  217 + float score = -std::numeric_limits<float>::max();
  218 + if ((query_subject_id != -1) && (target_subject_id != -1)) {
  219 + TRY(ppr_get_subject_similarity_score(context, simmat, query_subject_id, target_subject_id, &score))
  220 + }
  221 + output->setRelative(score, i, j);
  222 + }
  223 + }
  224 + ppr_free_similarity_matrix(simmat);
  225 + }
  226 +
  227 + void enroll(const TemplateList &templates, ppr_gallery_type *gallery, QList<int> &subject_ids) const
  228 + {
  229 + int subject_id = 0, face_id = 0;
  230 + foreach (const Template &src, templates) {
  231 + if (!src.empty() && src.m().data) {
  232 + foreach (const cv::Mat &m, src) {
  233 + ppr_face_type face;
  234 + createFace(m, &face);
  235 + TRY(ppr_add_face(context, gallery, face, subject_id, face_id))
  236 + face_id++;
  237 + ppr_free_face(face);
  238 + }
  239 + subject_ids.append(subject_id);
  240 + subject_id++;
  241 + } else {
  242 + subject_ids.append(-1);
  243 + }
  244 + }
  245 + }
  246 +
208 }; 247 };
209 248
210 /*! 249 /*!
@@ -294,6 +333,7 @@ class PP5EnrollTransform : public UntrainableMetaTransform @@ -294,6 +333,7 @@ class PP5EnrollTransform : public UntrainableMetaTransform
294 333
295 BR_REGISTER(Transform, PP5EnrollTransform) 334 BR_REGISTER(Transform, PP5EnrollTransform)
296 335
  336 +
297 /*! 337 /*!
298 * \ingroup distances 338 * \ingroup distances
299 * \brief Compare templates with PP5 339 * \brief Compare templates with PP5
@@ -351,44 +391,6 @@ class PP5CompareDistance : public Distance @@ -351,44 +391,6 @@ class PP5CompareDistance : public Distance
351 ppr_free_gallery(query_gallery); 391 ppr_free_gallery(query_gallery);
352 } 392 }
353 393
354 - void compareNative(ppr_gallery_type target, const QList<int> &targetIDs, ppr_gallery_type query, const QList<int> &queryIDs, Output *output) const  
355 - {  
356 - ppr_similarity_matrix_type simmat;  
357 - TRY(ppr_compare_galleries(context, query, target, &simmat))  
358 - for (int i=0; i<queryIDs.size(); i++) {  
359 - int query_subject_id = queryIDs[i];  
360 - for (int j=0; j<targetIDs.size(); j++) {  
361 - int target_subject_id = targetIDs[j];  
362 - float score = -std::numeric_limits<float>::max();  
363 - if ((query_subject_id != -1) && (target_subject_id != -1)) {  
364 - TRY(ppr_get_subject_similarity_score(context, simmat, query_subject_id, target_subject_id, &score))  
365 - }  
366 - output->setRelative(score, i, j);  
367 - }  
368 - }  
369 - ppr_free_similarity_matrix(simmat);  
370 - }  
371 -  
372 - void enroll(const TemplateList &templates, ppr_gallery_type *gallery, QList<int> &subject_ids) const  
373 - {  
374 - int subject_id = 0, face_id = 0;  
375 - foreach (const Template &src, templates) {  
376 - if (!src.empty() && src.m().data) {  
377 - foreach (const cv::Mat &m, src) {  
378 - ppr_face_type face;  
379 - createFace(m, &face);  
380 - TRY(ppr_add_face(context, gallery, face, subject_id, face_id))  
381 - face_id++;  
382 - ppr_free_face(face);  
383 - }  
384 - subject_ids.append(subject_id);  
385 - subject_id++;  
386 - } else {  
387 - subject_ids.append(-1);  
388 - }  
389 - }  
390 - }  
391 -  
392 NativeGallery cacheRetain(const File &gallery) const 394 NativeGallery cacheRetain(const File &gallery) const
393 { 395 {
394 QMutexLocker locker(&cacheLock); 396 QMutexLocker locker(&cacheLock);
@@ -439,4 +441,69 @@ class PP5CompareDistance : public Distance @@ -439,4 +441,69 @@ class PP5CompareDistance : public Distance
439 441
440 BR_REGISTER(Distance, PP5CompareDistance) 442 BR_REGISTER(Distance, PP5CompareDistance)
441 443
  444 +class PP5GalleryTransform: public UntrainableMetaTransform
  445 + , public PP5Context
  446 +{
  447 + Q_OBJECT
  448 + Q_PROPERTY(QString junk READ get_junk WRITE set_junk RESET reset_junk STORED false)
  449 + Q_PROPERTY(QString galleryName READ get_galleryName WRITE set_galleryName RESET reset_galleryName STORED false)
  450 + BR_PROPERTY(QString, junk, "")
  451 + BR_PROPERTY(QString, galleryName, "")
  452 +
  453 + ppr_gallery_type target;
  454 + QList<int> targetIDs;
  455 +
  456 + void project(const Template & src, Template & dst) const
  457 + {
  458 + TemplateList temp, output;
  459 + temp.append(src);
  460 + project(temp, output);
  461 + if (!output.empty())
  462 + dst = output[0];
  463 + }
  464 +
  465 + void project(const TemplateList & src, TemplateList & dst) const
  466 + {
  467 + dst.clear();
  468 + QList<int> queryIDs;
  469 +
  470 + ppr_gallery_type query;
  471 + ppr_create_gallery(context, &query);
  472 + enroll(src,&query, queryIDs);
  473 +
  474 + ppr_similarity_matrix_type simmat;
  475 +
  476 + TRY(ppr_compare_galleries(context, query, target, &simmat))
  477 +
  478 + for (int i=0; i<queryIDs.size(); i++) {
  479 + dst.append(Template());
  480 + dst[i].file = src[i].file;
  481 + dst[i].m() = cv::Mat(1,targetIDs.size(), CV_32FC1);
  482 +
  483 + int query_subject_id = queryIDs[i];
  484 + for (int j=0; j<targetIDs.size(); j++) {
  485 + int target_subject_id = targetIDs[j];
  486 + float score = -std::numeric_limits<float>::max();
  487 + if ((query_subject_id != -1) && (target_subject_id != -1)) {
  488 + TRY(ppr_get_subject_similarity_score(context, simmat, query_subject_id, target_subject_id, &score))
  489 + }
  490 + dst[i].m().at<float>(0,j) = score;
  491 + }
  492 + }
  493 +
  494 + ppr_free_similarity_matrix(simmat);
  495 + ppr_free_gallery(query);
  496 + }
  497 +
  498 + void init()
  499 + {
  500 + // set up the gallery
  501 + ppr_create_gallery(context, &target);
  502 + TemplateList templates = TemplateList::fromGallery(galleryName);
  503 + enroll(templates,&target, targetIDs);
  504 + }
  505 +};
  506 +
  507 +BR_REGISTER(Transform, PP5GalleryTransform)
  508 +
442 #include "plugins/pp5.moc" 509 #include "plugins/pp5.moc"