Commit a438d3fa911fe599826f0bef120a3eefeb9112eb
1 parent
7c9ace46
Refactor PP5 comparison handling
Introduce PP5GalleryTransform, a transform that compares incoming templates against a fixed gallery (thereby avoiding the cost of repeatedly setting up pp5 galleries for the same templates). Modify AlgorithmCore to support supplying Transforms to the right of the algorithm string, in this case ! should be used instead of :.
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" |