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 27 {
28 28 QSharedPointer<Transform> transform;
29 29 QSharedPointer<Distance> distance;
  30 + QString galleryCompareString;
30 31  
31 32 QString transformString;
32 33 QString distanceString;
... ... @@ -147,9 +148,6 @@ struct AlgorithmCore
147 148 Gallery *temp = Gallery::make(input);
148 149 qint64 total = temp->totalSize();
149 150  
150   - Globals->currentStep = 0;
151   - Globals->totalSteps = total;
152   -
153 151 QScopedPointer<Transform> basePipe;
154 152  
155 153 QString pipeDesc = "GalleryOutput("+gallery.flat()+")+ProgressCounter("+QString::number(total)+")+Discard";
... ... @@ -189,6 +187,8 @@ struct AlgorithmCore
189 187 wrapper->init();
190 188  
191 189 Globals->startTime.start();
  190 + Globals->currentStep = 0;
  191 + Globals->totalSteps = total;
192 192  
193 193 TemplateList data, output;
194 194 data.append(input);
... ... @@ -335,7 +335,7 @@ struct AlgorithmCore
335 335 output.isNull() ? "" : qPrintable(" to " + output.flat()));
336 336  
337 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 339 return;
340 340  
341 341 // Are we comparing the same gallery against itself?
... ... @@ -442,8 +442,11 @@ struct AlgorithmCore
442 442 // The actual comparison step is done by a GalleryCompare transform, which has a Distance, and a gallery as data.
443 443 // Incoming templates are compared against the templates in the gallery, and the output is the resulting score
444 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 451 QScopedPointer<Transform> compareRegion;
449 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 522  
520 523 // Set up progress counting variables
521 524 Globals->currentStep = 0;
  525 + Globals->currentProgress = 0;
522 526 Globals->totalSteps = rowSize;
523 527 Globals->startTime.start();
524 528  
... ... @@ -553,19 +557,27 @@ private:
553 557 if (Globals->abbreviations.contains(description))
554 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 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 566 transformString = words[0];
562 567  
563   -
564 568 //! [Creating the template generation and comparison methods]
565 569 transform = QSharedPointer<Transform>(Transform::make(words[0], NULL));
566 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 582 //! [Creating the template generation and comparison methods]
571 583 }
... ...
openbr/openbr_plugin.cpp
... ... @@ -875,7 +875,7 @@ void br::Context::printStatus()
875 875 const float p = progress();
876 876 if (p < 1) {
877 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 879 fflush(stderr);
880 880 }
881 881 }
... ...
openbr/plugins/gallery.cpp
... ... @@ -129,7 +129,7 @@ class BinaryGallery : public Gallery
129 129 if (t.isEmpty() && t.file.isNull())
130 130 continue;
131 131 templates.append(t);
132   - templates.last().file.set("progress", totalSize());
  132 + templates.last().file.set("progress", position());
133 133  
134 134 // Special case for pipes where we want to process data as soon as it is available
135 135 if (gallery.isSequential())
... ...
openbr/plugins/misc.cpp
... ... @@ -625,11 +625,18 @@ class ProgressCounterTransform : public TimeVaryingTransform
625 625 dst = src;
626 626  
627 627 qint64 elapsed = timer.elapsed();
628   -
  628 + int last_frame = -2;
629 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 642 // updated every second
... ... @@ -650,13 +657,17 @@ class ProgressCounterTransform : public TimeVaryingTransform
650 657 {
651 658 (void) data;
652 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 666 void init()
657 667 {
658 668 timer.start();
659 669 Globals->currentStep = 0;
  670 + Globals->currentProgress = 0;
660 671 }
661 672  
662 673 public:
... ... @@ -713,26 +724,26 @@ class OutputTransform : public TimeVaryingTransform
713 724 currentCol++;
714 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 45 void initialize() const
46 46 {
47 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 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 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 85 default_settings.recognition.automatically_extract_templates = 1;
86 86 default_settings.recognition.enable_comparison = 1;
87 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 89 default_settings.recognition.recognizer = PPR_RECOGNIZER_MULTI_POSE;
90 90 TRY(ppr_initialize_context(default_settings, &context))
91 91 }
... ... @@ -205,6 +205,45 @@ struct PP5Context
205 205  
206 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 333  
295 334 BR_REGISTER(Transform, PP5EnrollTransform)
296 335  
  336 +
297 337 /*!
298 338 * \ingroup distances
299 339 * \brief Compare templates with PP5
... ... @@ -351,44 +391,6 @@ class PP5CompareDistance : public Distance
351 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 394 NativeGallery cacheRetain(const File &gallery) const
393 395 {
394 396 QMutexLocker locker(&cacheLock);
... ... @@ -439,4 +441,69 @@ class PP5CompareDistance : public Distance
439 441  
440 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 509 #include "plugins/pp5.moc"
... ...