Commit bc16c3ddb3a63e30da08cdf8324531126a90937f

Authored by Charles Otto
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).
openbr/openbr_plugin.h
@@ -1085,6 +1085,8 @@ public: @@ -1085,6 +1085,8 @@ public:
1085 return dst; 1085 return dst;
1086 } 1086 }
1087 1087
  1088 + virtual Transform * pseudoCopy() { return this;}
  1089 +
1088 protected: 1090 protected:
1089 Transform(bool independent = true, bool trainable = true); /*!< \brief Construct a transform. */ 1091 Transform(bool independent = true, bool trainable = true); /*!< \brief Construct a transform. */
1090 inline Transform *make(const QString &description) { return make(description, this); } /*!< \brief Make a subtransform. */ 1092 inline Transform *make(const QString &description) { return make(description, this); } /*!< \brief Make a subtransform. */
@@ -1165,6 +1167,12 @@ public: @@ -1165,6 +1167,12 @@ public:
1165 } 1167 }
1166 } 1168 }
1167 1169
  1170 + virtual Transform * pseudoCopy()
  1171 + {
  1172 + return this->clone();
  1173 + }
  1174 +
  1175 +
1168 protected: 1176 protected:
1169 TimeVaryingTransform(bool independent = true, bool trainable = true) : Transform(independent, trainable) {} 1177 TimeVaryingTransform(bool independent = true, bool trainable = true) : Transform(independent, trainable) {}
1170 }; 1178 };
@@ -1243,6 +1251,38 @@ public: @@ -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 protected: 1286 protected:
1247 bool isTimeVarying; 1287 bool isTimeVarying;
1248 1288
openbr/plugins/meta.cpp
@@ -21,6 +21,7 @@ @@ -21,6 +21,7 @@
21 #include "openbr/core/common.h" 21 #include "openbr/core/common.h"
22 #include "openbr/core/opencvutils.h" 22 #include "openbr/core/opencvutils.h"
23 #include "openbr/core/qtutils.h" 23 #include "openbr/core/qtutils.h"
  24 +#include "openbr/core/resource.h"
24 25
25 using namespace cv; 26 using namespace cv;
26 27
@@ -183,7 +184,6 @@ class PipeTransform : public CompositeTransform @@ -183,7 +184,6 @@ class PipeTransform : public CompositeTransform
183 } 184 }
184 } 185 }
185 186
186 -  
187 protected: 187 protected:
188 // Template list project -- process templates in parallel through Transform::project 188 // Template list project -- process templates in parallel through Transform::project
189 // or if parallelism is disabled, handle them sequentially 189 // or if parallelism is disabled, handle them sequentially
@@ -590,6 +590,56 @@ static void _projectList(const Transform *transform, const TemplateList *src, Te @@ -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 class DistributeTemplateTransform : public MetaTransform 643 class DistributeTemplateTransform : public MetaTransform
594 { 644 {
595 Q_OBJECT 645 Q_OBJECT
@@ -598,6 +648,16 @@ class DistributeTemplateTransform : public MetaTransform @@ -598,6 +648,16 @@ class DistributeTemplateTransform : public MetaTransform
598 648
599 public: 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 void train(const TemplateList &data) 661 void train(const TemplateList &data)
602 { 662 {
603 transform->train(data); 663 transform->train(data);
@@ -620,15 +680,6 @@ public: @@ -620,15 +680,6 @@ public:
620 // Process the single elemnt templates in parallel if parallelism is enabled. 680 // Process the single elemnt templates in parallel if parallelism is enabled.
621 void project(const TemplateList &src, TemplateList &dst) const 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 // Pre-allocate output for each template 683 // Pre-allocate output for each template
633 QList<TemplateList> output_buffer; 684 QList<TemplateList> output_buffer;
634 output_buffer.reserve(src.size()); 685 output_buffer.reserve(src.size());
@@ -655,15 +706,16 @@ public: @@ -655,15 +706,16 @@ public:
655 706
656 void projectUpdate(const TemplateList &src, TemplateList &dst) 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 BR_REGISTER(Transform, DistributeTemplateTransform) 721 BR_REGISTER(Transform, DistributeTemplateTransform)