Commit 63596a8c07e442170ff00bbe05eeed4b53a4faf2
Merge pull request #26 from biometrics/variable_output
Structural changes to the basic multi-template enrollment operation
Showing
5 changed files
with
112 additions
and
128 deletions
sdk/core/core.cpp
| ... | ... | @@ -262,6 +262,9 @@ private: |
| 262 | 262 | QStringList words = QtUtils::parse(description, ':'); |
| 263 | 263 | if (words.size() > 2) qFatal("Invalid algorithm format."); |
| 264 | 264 | |
| 265 | + words[0].prepend("DistributeTemplate("); | |
| 266 | + words[0].append(")"); | |
| 267 | + | |
| 265 | 268 | transform = QSharedPointer<Transform>(Transform::make(words[0], NULL)); |
| 266 | 269 | if (words.size() > 1) distance = QSharedPointer<Distance>(Distance::make(words[1], NULL)); |
| 267 | 270 | } | ... | ... |
sdk/openbr_plugin.cpp
| ... | ... | @@ -1202,10 +1202,8 @@ Transform *Transform::make(QString str, QObject *parent) |
| 1202 | 1202 | if (Globals->abbreviations.contains(str)) |
| 1203 | 1203 | return make(Globals->abbreviations[str], parent); |
| 1204 | 1204 | |
| 1205 | - { // Check for use of '!' as shorthand for Expand(...) | |
| 1206 | - QStringList words = parse(str, '!'); | |
| 1207 | - if (words.size() > 1) | |
| 1208 | - return make("Expand([" + words.join(",") + "])", parent); | |
| 1205 | + { // Check for use of '!' as shorthand for Expand | |
| 1206 | + str.replace("!","+Expand+"); | |
| 1209 | 1207 | } |
| 1210 | 1208 | |
| 1211 | 1209 | { // Check for use of '+' as shorthand for Pipe(...) |
| ... | ... | @@ -1250,17 +1248,6 @@ Transform *Transform::clone() const |
| 1250 | 1248 | return clone; |
| 1251 | 1249 | } |
| 1252 | 1250 | |
| 1253 | -static void _project(const Transform *transform, const Template *src, Template *dst) | |
| 1254 | -{ | |
| 1255 | - try { | |
| 1256 | - transform->project(*src, *dst); | |
| 1257 | - } catch (...) { | |
| 1258 | - qWarning("Exception triggered when processing %s with transform %s", qPrintable(src->file.flat()), qPrintable(transform->objectName())); | |
| 1259 | - *dst = Template(src->file); | |
| 1260 | - dst->file.set("FTE", true); | |
| 1261 | - } | |
| 1262 | -} | |
| 1263 | - | |
| 1264 | 1251 | static void _backProject(const Transform *transform, const Template *dst, Template *src) |
| 1265 | 1252 | { |
| 1266 | 1253 | try { |
| ... | ... | @@ -1273,17 +1260,25 @@ static void _backProject(const Transform *transform, const Template *dst, Templa |
| 1273 | 1260 | } |
| 1274 | 1261 | |
| 1275 | 1262 | |
| 1263 | + | |
| 1264 | +// Default project(TemplateList) -- call project(template) separately for each input | |
| 1265 | +// template | |
| 1276 | 1266 | void Transform::project(const TemplateList &src, TemplateList &dst) const |
| 1277 | 1267 | { |
| 1278 | - dst.reserve(src.size()); | |
| 1279 | - for (int i=0; i<src.size(); i++) dst.append(Template()); | |
| 1280 | - | |
| 1281 | - QList< QFuture<void> > futures; | |
| 1282 | - if (Globals->parallelism) futures.reserve(src.size()); | |
| 1283 | - for (int i=0; i<src.size(); i++) | |
| 1284 | - if (Globals->parallelism) futures.append(QtConcurrent::run(_project, this, &src[i], &dst[i])); | |
| 1285 | - else _project (this, &src[i], &dst[i]); | |
| 1286 | - if (Globals->parallelism) Globals->trackFutures(futures); | |
| 1268 | + dst.clear(); | |
| 1269 | + | |
| 1270 | + // Project templates derived from a single image, default implementation: project each | |
| 1271 | + // input template to an ouptut template individually. | |
| 1272 | + foreach(const Template & src_template, src) { | |
| 1273 | + dst.append(Template(src_template.file)); | |
| 1274 | + try { | |
| 1275 | + project(src_template, dst.back()); | |
| 1276 | + } catch (...) { | |
| 1277 | + qWarning("Exception triggered when processing %s with transform %s", qPrintable(src_template.file.flat()), qPrintable(objectName())); | |
| 1278 | + dst.back() = Template(src_template.file); | |
| 1279 | + dst.back().file.set("FTE", true); | |
| 1280 | + } | |
| 1281 | + } | |
| 1287 | 1282 | } |
| 1288 | 1283 | |
| 1289 | 1284 | void Transform::backProject(const Template &dst, Template &src) const | ... | ... |
sdk/plugins/gallery.cpp
| ... | ... | @@ -590,10 +590,10 @@ class dbGallery : public Gallery |
| 590 | 590 | } |
| 591 | 591 | |
| 592 | 592 | QStringList labels = entries.keys(); |
| 593 | + qSort(labels); | |
| 594 | + | |
| 593 | 595 | if (hasFilter && ((labels.size() > numSubjects) || (numSubjects == std::numeric_limits<int>::max()))) |
| 594 | 596 | std::random_shuffle(labels.begin(), labels.end()); |
| 595 | - else | |
| 596 | - qSort(labels); | |
| 597 | 597 | |
| 598 | 598 | foreach (const QString &label, labels) { |
| 599 | 599 | QList<Entry> entryList = entries[label]; | ... | ... |
sdk/plugins/meta.cpp
| ... | ... | @@ -86,66 +86,6 @@ static void incrementStep() |
| 86 | 86 | } |
| 87 | 87 | |
| 88 | 88 | /*! |
| 89 | - * \brief Use Expanded after basic calls that take a template list, used to implement ExpandTransform | |
| 90 | - */ | |
| 91 | -class ExpandDecorator : public Transform | |
| 92 | -{ | |
| 93 | - Q_OBJECT | |
| 94 | - | |
| 95 | - Q_PROPERTY(br::Transform* transform READ get_transform WRITE set_transform RESET reset_transform) | |
| 96 | - BR_PROPERTY(br::Transform*, transform, NULL) | |
| 97 | - | |
| 98 | -public: | |
| 99 | - ExpandDecorator(Transform * input) | |
| 100 | - { | |
| 101 | - transform = input; | |
| 102 | - transform->setParent(this); | |
| 103 | - file = transform->file; | |
| 104 | - setObjectName(transform->objectName()); | |
| 105 | - } | |
| 106 | - | |
| 107 | - void train(const TemplateList &data) | |
| 108 | - { | |
| 109 | - transform->train(data); | |
| 110 | - } | |
| 111 | - | |
| 112 | - void project(const Template &src, Template &dst) const | |
| 113 | - { | |
| 114 | - transform->project(src, dst); | |
| 115 | - } | |
| 116 | - | |
| 117 | - void project(const TemplateList &src, TemplateList &dst) const | |
| 118 | - { | |
| 119 | - transform->project(src, dst); | |
| 120 | - dst = Expanded(dst); | |
| 121 | - } | |
| 122 | - | |
| 123 | - | |
| 124 | - void projectUpdate(const Template &src, Template &dst) | |
| 125 | - { | |
| 126 | - transform->projectUpdate(src, dst); | |
| 127 | - } | |
| 128 | - | |
| 129 | - void projectUpdate(const TemplateList & src, TemplateList & dst) | |
| 130 | - { | |
| 131 | - transform->projectUpdate(src, dst); | |
| 132 | - dst = Expanded(dst); | |
| 133 | - } | |
| 134 | - | |
| 135 | - bool timeVarying() const | |
| 136 | - { | |
| 137 | - return transform->timeVarying(); | |
| 138 | - } | |
| 139 | - | |
| 140 | - void finalize(TemplateList & output) | |
| 141 | - { | |
| 142 | - transform->finalize(output); | |
| 143 | - output = Expanded(output); | |
| 144 | - } | |
| 145 | - | |
| 146 | -}; | |
| 147 | - | |
| 148 | -/*! | |
| 149 | 89 | * \brief A MetaTransform that aggregates some sub-transforms |
| 150 | 90 | */ |
| 151 | 91 | class BR_EXPORT CompositeTransform : public TimeVaryingTransform |
| ... | ... | @@ -291,12 +231,9 @@ protected: |
| 291 | 231 | // or if parallelism is disabled, handle them sequentially |
| 292 | 232 | void _project(const TemplateList &src, TemplateList &dst) const |
| 293 | 233 | { |
| 294 | - if (Globals->parallelism < 0) { | |
| 295 | - dst = src; | |
| 296 | - foreach (const Transform *f, transforms) | |
| 297 | - dst >> *f; | |
| 298 | - } else { | |
| 299 | - Transform::project(src, dst); | |
| 234 | + dst = src; | |
| 235 | + foreach (const Transform *f, transforms) { | |
| 236 | + dst >> *f; | |
| 300 | 237 | } |
| 301 | 238 | } |
| 302 | 239 | |
| ... | ... | @@ -320,40 +257,26 @@ BR_REGISTER(Transform, PipeTransform) |
| 320 | 257 | |
| 321 | 258 | /*! |
| 322 | 259 | * \ingroup transforms |
| 323 | - * \brief Transforms in series with expansion step. | |
| 260 | + * \brief Performs an expansion step on input templatelists | |
| 324 | 261 | * \author Josh Klontz \cite jklontz |
| 325 | 262 | * |
| 326 | - * The source br::Template is given to the first transform and the resulting br::Template is passed to the next transform, etc. | |
| 327 | - * Each matrix is expanded into its own template between steps. | |
| 263 | + * Each matrix in an input Template is expanded into its own template. | |
| 328 | 264 | * |
| 329 | 265 | * \see PipeTransform |
| 330 | 266 | */ |
| 331 | -class ExpandTransform : public PipeTransform | |
| 267 | +class ExpandTransform : public UntrainableMetaTransform | |
| 332 | 268 | { |
| 333 | 269 | Q_OBJECT |
| 334 | 270 | |
| 335 | - void init() | |
| 271 | + virtual void project(const TemplateList &src, TemplateList &dst) const | |
| 336 | 272 | { |
| 337 | - for (int i = 0; i < transforms.size(); i++) | |
| 338 | - { | |
| 339 | - transforms[i] = new ExpandDecorator(transforms[i]); | |
| 340 | - } | |
| 341 | - // Need to call this to set up timevariance correctly, and it won't | |
| 342 | - // be called automatically | |
| 343 | - CompositeTransform::init(); | |
| 273 | + dst = Expanded(src); | |
| 344 | 274 | } |
| 345 | 275 | |
| 346 | -protected: | |
| 347 | - | |
| 348 | - // Template list project -- project through transforms sequentially, | |
| 349 | - // then expand the results, can't use Transform::Project(templateList) since | |
| 350 | - // we need to expand between tranforms, so actually do need to overload this method | |
| 351 | - void _project(const TemplateList &src, TemplateList &dst) const | |
| 276 | + virtual void project(const Template & src, Template & dst) const | |
| 352 | 277 | { |
| 353 | - dst = src; | |
| 354 | - for (int i=0; i<transforms.size(); i++) { | |
| 355 | - dst >> *transforms[i]; | |
| 356 | - } | |
| 278 | + qFatal("this has gone bad"); | |
| 279 | + (void) src; (void) dst; | |
| 357 | 280 | } |
| 358 | 281 | }; |
| 359 | 282 | |
| ... | ... | @@ -405,12 +328,12 @@ class ForkTransform : public CompositeTransform |
| 405 | 328 | { |
| 406 | 329 | dst = src; |
| 407 | 330 | dst.reserve(src.size()); |
| 408 | - for (int i=0; i<src.size(); i++) dst.append(Template()); | |
| 331 | + for (int i=0; i<src.size(); i++) dst.append(Template(src[i].file)); | |
| 409 | 332 | foreach (Transform *f, transforms) { |
| 410 | 333 | TemplateList m; |
| 411 | 334 | f->projectUpdate(src, m); |
| 412 | 335 | if (m.size() != dst.size()) qFatal("TemplateList is of an unexpected size."); |
| 413 | - for (int i=0; i<src.size(); i++) dst[i].append(m[i]); | |
| 336 | + for (int i=0; i<src.size(); i++) dst[i].merge(m[i]); | |
| 414 | 337 | } |
| 415 | 338 | } |
| 416 | 339 | |
| ... | ... | @@ -460,17 +383,13 @@ protected: |
| 460 | 383 | |
| 461 | 384 | void _project(const TemplateList &src, TemplateList &dst) const |
| 462 | 385 | { |
| 463 | - if (Globals->parallelism < 0) { | |
| 464 | - dst.reserve(src.size()); | |
| 465 | - for (int i=0; i<src.size(); i++) dst.append(Template()); | |
| 466 | - foreach (const Transform *f, transforms) { | |
| 467 | - TemplateList m; | |
| 468 | - f->project(src, m); | |
| 469 | - if (m.size() != dst.size()) qFatal("TemplateList is of an unexpected size."); | |
| 470 | - for (int i=0; i<src.size(); i++) dst[i].append(m[i]); | |
| 471 | - } | |
| 472 | - } else { | |
| 473 | - Transform::project(src, dst); | |
| 386 | + dst.reserve(src.size()); | |
| 387 | + for (int i=0; i<src.size(); i++) dst.append(Template(src[i].file)); | |
| 388 | + foreach (const Transform *f, transforms) { | |
| 389 | + TemplateList m; | |
| 390 | + f->project(src, m); | |
| 391 | + if (m.size() != dst.size()) qFatal("TemplateList is of an unexpected size."); | |
| 392 | + for (int i=0; i<src.size(); i++) dst[i].merge(m[i]); | |
| 474 | 393 | } |
| 475 | 394 | } |
| 476 | 395 | |
| ... | ... | @@ -670,6 +589,73 @@ class FTETransform : public Transform |
| 670 | 589 | |
| 671 | 590 | BR_REGISTER(Transform, FTETransform) |
| 672 | 591 | |
| 592 | + | |
| 593 | +static void _projectList(const Transform *transform, const TemplateList *src, TemplateList *dst) | |
| 594 | +{ | |
| 595 | + transform->project(*src, *dst); | |
| 596 | +} | |
| 597 | + | |
| 598 | + | |
| 599 | +class DistributeTemplateTransform : public UntrainableMetaTransform | |
| 600 | +{ | |
| 601 | + Q_OBJECT | |
| 602 | + Q_PROPERTY(br::Transform* transform READ get_transform WRITE set_transform RESET reset_transform) | |
| 603 | + BR_PROPERTY(br::Transform*, transform, NULL) | |
| 604 | + | |
| 605 | +public: | |
| 606 | + | |
| 607 | + void project(const Template &src, Template &dst) const | |
| 608 | + { | |
| 609 | + TemplateList input; | |
| 610 | + input.append(src); | |
| 611 | + TemplateList output; | |
| 612 | + project(input, output); | |
| 613 | + | |
| 614 | + if (output.size() != 1) qFatal("output contains more than 1 template"); | |
| 615 | + else dst = output[0]; | |
| 616 | + } | |
| 617 | + | |
| 618 | + | |
| 619 | + // For each input template, form a single element TemplateList, push all those | |
| 620 | + // lists through transform, and form dst by concatenating the results. | |
| 621 | + // Process the single elemnt templates in parallel if parallelism is enabled. | |
| 622 | + void project(const TemplateList &src, TemplateList &dst) const | |
| 623 | + { | |
| 624 | + // Pre-allocate output for each template | |
| 625 | + QList<TemplateList> output_buffer; | |
| 626 | + output_buffer.reserve(src.size()); | |
| 627 | + | |
| 628 | + // Can't declare this local to the loop because it would go out of scope | |
| 629 | + QList<TemplateList> input_buffer; | |
| 630 | + input_buffer.reserve(src.size()); | |
| 631 | + | |
| 632 | + for (int i =0; i < src.size();i++) { | |
| 633 | + input_buffer.append(TemplateList()); | |
| 634 | + output_buffer.append(TemplateList()); | |
| 635 | + } | |
| 636 | + | |
| 637 | + QList< QFuture<void> > futures; | |
| 638 | + futures.reserve(src.size()); | |
| 639 | + for (int i=0; i<src.size(); i++) { | |
| 640 | + input_buffer[i].append(src[i]); | |
| 641 | + if (Globals->parallelism) | |
| 642 | + futures.append(QtConcurrent::run(_projectList, transform, &input_buffer[i], &output_buffer[i])); | |
| 643 | + else | |
| 644 | + _projectList(transform, &input_buffer[i], &output_buffer[i]); | |
| 645 | + } | |
| 646 | + | |
| 647 | + if (Globals->parallelism) | |
| 648 | + Globals->trackFutures(futures); | |
| 649 | + | |
| 650 | + for (int i=0; i<src.size(); i++) dst.append(output_buffer[i]); | |
| 651 | + } | |
| 652 | + | |
| 653 | + | |
| 654 | + private: | |
| 655 | + | |
| 656 | +}; | |
| 657 | +BR_REGISTER(Transform, DistributeTemplateTransform) | |
| 658 | + | |
| 673 | 659 | } // namespace br |
| 674 | 660 | |
| 675 | 661 | #include "meta.moc" | ... | ... |