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 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)
... ...