Commit cdb6b4fb4004e23c7e759d28efe1373576d4a180
Merge pull request #213 from biometrics/inline_pp5
Refactor PP5 comparison handling
Showing
5 changed files
with
167 additions
and
77 deletions
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" |