Commit bc16c3ddb3a63e30da08cdf8324531126a90937f
1 parent
b48eeb8b
Give Distribute better support for handling timevarying transforms
Introduce 'pseudocopy' operation which, which if called on a time-invariant transform, returns the transform, but if called on a time-varying transform returns a copy of the current state of the time-varying transform. Composite transforms apply pseudocopy to their children (if they contain any time-varying transforms). Introduce a wrapper class that uses Resource to let time-varying transforms act like time-invariant transforms, currently only used by distribute (it is assumed that any work that is being distributed is in fact independent).
Showing
2 changed files
with
108 additions
and
16 deletions
openbr/openbr_plugin.h
| ... | ... | @@ -1085,6 +1085,8 @@ public: |
| 1085 | 1085 | return dst; |
| 1086 | 1086 | } |
| 1087 | 1087 | |
| 1088 | + virtual Transform * pseudoCopy() { return this;} | |
| 1089 | + | |
| 1088 | 1090 | protected: |
| 1089 | 1091 | Transform(bool independent = true, bool trainable = true); /*!< \brief Construct a transform. */ |
| 1090 | 1092 | inline Transform *make(const QString &description) { return make(description, this); } /*!< \brief Make a subtransform. */ |
| ... | ... | @@ -1165,6 +1167,12 @@ public: |
| 1165 | 1167 | } |
| 1166 | 1168 | } |
| 1167 | 1169 | |
| 1170 | + virtual Transform * pseudoCopy() | |
| 1171 | + { | |
| 1172 | + return this->clone(); | |
| 1173 | + } | |
| 1174 | + | |
| 1175 | + | |
| 1168 | 1176 | protected: |
| 1169 | 1177 | TimeVaryingTransform(bool independent = true, bool trainable = true) : Transform(independent, trainable) {} |
| 1170 | 1178 | }; |
| ... | ... | @@ -1243,6 +1251,38 @@ public: |
| 1243 | 1251 | } |
| 1244 | 1252 | } |
| 1245 | 1253 | |
| 1254 | + Transform * pseudoCopy() | |
| 1255 | + { | |
| 1256 | + if (!timeVarying()) | |
| 1257 | + return this; | |
| 1258 | + | |
| 1259 | + QString name = metaObject()->className(); | |
| 1260 | + name.replace("Transform",""); | |
| 1261 | + name += "([])"; | |
| 1262 | + name.replace("br::",""); | |
| 1263 | + CompositeTransform * output = dynamic_cast<CompositeTransform *>(Transform::make(name, NULL)); | |
| 1264 | + | |
| 1265 | + if (output == NULL) | |
| 1266 | + qFatal("Dynamic cast failed!"); | |
| 1267 | + | |
| 1268 | + foreach(Transform* t, transforms ) | |
| 1269 | + { | |
| 1270 | + Transform * maybe_copy = t->pseudoCopy(); | |
| 1271 | + if (maybe_copy->parent() == NULL) | |
| 1272 | + maybe_copy->setParent(output); | |
| 1273 | + output->transforms.append(t->pseudoCopy()); | |
| 1274 | + } | |
| 1275 | + | |
| 1276 | + output->file = this->file; | |
| 1277 | + output->classes = classes; | |
| 1278 | + output->instances = instances; | |
| 1279 | + output->fraction = fraction; | |
| 1280 | + | |
| 1281 | + output->init(); | |
| 1282 | + | |
| 1283 | + return output; | |
| 1284 | + } | |
| 1285 | + | |
| 1246 | 1286 | protected: |
| 1247 | 1287 | bool isTimeVarying; |
| 1248 | 1288 | ... | ... |
openbr/plugins/meta.cpp
| ... | ... | @@ -21,6 +21,7 @@ |
| 21 | 21 | #include "openbr/core/common.h" |
| 22 | 22 | #include "openbr/core/opencvutils.h" |
| 23 | 23 | #include "openbr/core/qtutils.h" |
| 24 | +#include "openbr/core/resource.h" | |
| 24 | 25 | |
| 25 | 26 | using namespace cv; |
| 26 | 27 | |
| ... | ... | @@ -183,7 +184,6 @@ class PipeTransform : public CompositeTransform |
| 183 | 184 | } |
| 184 | 185 | } |
| 185 | 186 | |
| 186 | - | |
| 187 | 187 | protected: |
| 188 | 188 | // Template list project -- process templates in parallel through Transform::project |
| 189 | 189 | // or if parallelism is disabled, handle them sequentially |
| ... | ... | @@ -590,6 +590,56 @@ static void _projectList(const Transform *transform, const TemplateList *src, Te |
| 590 | 590 | } |
| 591 | 591 | |
| 592 | 592 | |
| 593 | +class TransformCopier : public ResourceMaker<Transform> | |
| 594 | +{ | |
| 595 | +public: | |
| 596 | + Transform * basis; | |
| 597 | + TransformCopier(Transform * _basis) | |
| 598 | + { | |
| 599 | + basis = _basis; | |
| 600 | + } | |
| 601 | + | |
| 602 | + virtual Transform *make() const | |
| 603 | + { | |
| 604 | + return basis->pseudoCopy(); | |
| 605 | + } | |
| 606 | + | |
| 607 | +}; | |
| 608 | + | |
| 609 | +class TimeInvariantWrapperTransform : public MetaTransform | |
| 610 | +{ | |
| 611 | +public: | |
| 612 | + Resource<Transform> transformSource; | |
| 613 | + | |
| 614 | + TimeInvariantWrapperTransform(Transform * basis) : transformSource(new TransformCopier(basis)) | |
| 615 | + { | |
| 616 | + baseTransform = basis; | |
| 617 | + } | |
| 618 | + | |
| 619 | + virtual void project(const Template &src, Template &dst) const | |
| 620 | + { | |
| 621 | + Transform * aTransform = transformSource.acquire(); | |
| 622 | + aTransform->projectUpdate(src,dst); | |
| 623 | + transformSource.release(aTransform); | |
| 624 | + } | |
| 625 | + | |
| 626 | + | |
| 627 | + void project(const TemplateList &src, TemplateList &dst) const | |
| 628 | + { | |
| 629 | + Transform * aTransform = transformSource.acquire(); | |
| 630 | + aTransform->projectUpdate(src,dst); | |
| 631 | + transformSource.release(aTransform); | |
| 632 | + } | |
| 633 | + | |
| 634 | + void train(const TemplateList &data) | |
| 635 | + { | |
| 636 | + baseTransform->train(data); | |
| 637 | + } | |
| 638 | + | |
| 639 | +private: | |
| 640 | + Transform * baseTransform; | |
| 641 | +}; | |
| 642 | + | |
| 593 | 643 | class DistributeTemplateTransform : public MetaTransform |
| 594 | 644 | { |
| 595 | 645 | Q_OBJECT |
| ... | ... | @@ -598,6 +648,16 @@ class DistributeTemplateTransform : public MetaTransform |
| 598 | 648 | |
| 599 | 649 | public: |
| 600 | 650 | |
| 651 | + Transform * pseudoCopy() | |
| 652 | + { | |
| 653 | + if (!transform->timeVarying()) | |
| 654 | + return this; | |
| 655 | + | |
| 656 | + DistributeTemplateTransform * output = new DistributeTemplateTransform; | |
| 657 | + output->transform = transform->pseudoCopy(); | |
| 658 | + return output; | |
| 659 | + } | |
| 660 | + | |
| 601 | 661 | void train(const TemplateList &data) |
| 602 | 662 | { |
| 603 | 663 | transform->train(data); |
| ... | ... | @@ -620,15 +680,6 @@ public: |
| 620 | 680 | // Process the single elemnt templates in parallel if parallelism is enabled. |
| 621 | 681 | void project(const TemplateList &src, TemplateList &dst) const |
| 622 | 682 | { |
| 623 | - // Little ugly, but if we own a timeVaryingTransform and this gets called | |
| 624 | - // cast off the const modifier and use projectUpdate. This allows us to | |
| 625 | - // act as a single point of entry. | |
| 626 | - if (transform->timeVarying()) | |
| 627 | - { | |
| 628 | - DistributeTemplateTransform * non_const = (DistributeTemplateTransform *) this; | |
| 629 | - non_const->projectUpdate(src,dst); | |
| 630 | - return; | |
| 631 | - } | |
| 632 | 683 | // Pre-allocate output for each template |
| 633 | 684 | QList<TemplateList> output_buffer; |
| 634 | 685 | output_buffer.reserve(src.size()); |
| ... | ... | @@ -655,15 +706,16 @@ public: |
| 655 | 706 | |
| 656 | 707 | void projectUpdate(const TemplateList &src, TemplateList &dst) |
| 657 | 708 | { |
| 658 | - if (!transform->timeVarying()) { | |
| 659 | - this->project(src, dst); | |
| 660 | - return; | |
| 661 | - } | |
| 662 | - this->transform->projectUpdate(src, dst); | |
| 709 | + this->project(src, dst); | |
| 710 | + return; | |
| 663 | 711 | } |
| 664 | 712 | |
| 713 | + void init() | |
| 714 | + { | |
| 665 | 715 | |
| 666 | - private: | |
| 716 | + if (transform && transform->timeVarying()) | |
| 717 | + transform = new br::TimeInvariantWrapperTransform(transform); | |
| 718 | + } | |
| 667 | 719 | |
| 668 | 720 | }; |
| 669 | 721 | BR_REGISTER(Transform, DistributeTemplateTransform) | ... | ... |