diff --git a/openbr/openbr_plugin.h b/openbr/openbr_plugin.h index 908764a..cbcf957 100644 --- a/openbr/openbr_plugin.h +++ b/openbr/openbr_plugin.h @@ -1085,6 +1085,8 @@ public: return dst; } + virtual Transform * pseudoCopy() { return this;} + protected: Transform(bool independent = true, bool trainable = true); /*!< \brief Construct a transform. */ inline Transform *make(const QString &description) { return make(description, this); } /*!< \brief Make a subtransform. */ @@ -1165,6 +1167,12 @@ public: } } + virtual Transform * pseudoCopy() + { + return this->clone(); + } + + protected: TimeVaryingTransform(bool independent = true, bool trainable = true) : Transform(independent, trainable) {} }; @@ -1243,6 +1251,38 @@ public: } } + Transform * pseudoCopy() + { + if (!timeVarying()) + return this; + + QString name = metaObject()->className(); + name.replace("Transform",""); + name += "([])"; + name.replace("br::",""); + CompositeTransform * output = dynamic_cast(Transform::make(name, NULL)); + + if (output == NULL) + qFatal("Dynamic cast failed!"); + + foreach(Transform* t, transforms ) + { + Transform * maybe_copy = t->pseudoCopy(); + if (maybe_copy->parent() == NULL) + maybe_copy->setParent(output); + output->transforms.append(t->pseudoCopy()); + } + + output->file = this->file; + output->classes = classes; + output->instances = instances; + output->fraction = fraction; + + output->init(); + + return output; + } + protected: bool isTimeVarying; diff --git a/openbr/plugins/meta.cpp b/openbr/plugins/meta.cpp index 4c7eee1..144d882 100644 --- a/openbr/plugins/meta.cpp +++ b/openbr/plugins/meta.cpp @@ -21,6 +21,7 @@ #include "openbr/core/common.h" #include "openbr/core/opencvutils.h" #include "openbr/core/qtutils.h" +#include "openbr/core/resource.h" using namespace cv; @@ -183,7 +184,6 @@ class PipeTransform : public CompositeTransform } } - protected: // Template list project -- process templates in parallel through Transform::project // or if parallelism is disabled, handle them sequentially @@ -590,6 +590,56 @@ static void _projectList(const Transform *transform, const TemplateList *src, Te } +class TransformCopier : public ResourceMaker +{ +public: + Transform * basis; + TransformCopier(Transform * _basis) + { + basis = _basis; + } + + virtual Transform *make() const + { + return basis->pseudoCopy(); + } + +}; + +class TimeInvariantWrapperTransform : public MetaTransform +{ +public: + Resource transformSource; + + TimeInvariantWrapperTransform(Transform * basis) : transformSource(new TransformCopier(basis)) + { + baseTransform = basis; + } + + virtual void project(const Template &src, Template &dst) const + { + Transform * aTransform = transformSource.acquire(); + aTransform->projectUpdate(src,dst); + transformSource.release(aTransform); + } + + + void project(const TemplateList &src, TemplateList &dst) const + { + Transform * aTransform = transformSource.acquire(); + aTransform->projectUpdate(src,dst); + transformSource.release(aTransform); + } + + void train(const TemplateList &data) + { + baseTransform->train(data); + } + +private: + Transform * baseTransform; +}; + class DistributeTemplateTransform : public MetaTransform { Q_OBJECT @@ -598,6 +648,16 @@ class DistributeTemplateTransform : public MetaTransform public: + Transform * pseudoCopy() + { + if (!transform->timeVarying()) + return this; + + DistributeTemplateTransform * output = new DistributeTemplateTransform; + output->transform = transform->pseudoCopy(); + return output; + } + void train(const TemplateList &data) { transform->train(data); @@ -620,15 +680,6 @@ public: // Process the single elemnt templates in parallel if parallelism is enabled. void project(const TemplateList &src, TemplateList &dst) const { - // Little ugly, but if we own a timeVaryingTransform and this gets called - // cast off the const modifier and use projectUpdate. This allows us to - // act as a single point of entry. - if (transform->timeVarying()) - { - DistributeTemplateTransform * non_const = (DistributeTemplateTransform *) this; - non_const->projectUpdate(src,dst); - return; - } // Pre-allocate output for each template QList output_buffer; output_buffer.reserve(src.size()); @@ -655,15 +706,16 @@ public: void projectUpdate(const TemplateList &src, TemplateList &dst) { - if (!transform->timeVarying()) { - this->project(src, dst); - return; - } - this->transform->projectUpdate(src, dst); + this->project(src, dst); + return; } + void init() + { - private: + if (transform && transform->timeVarying()) + transform = new br::TimeInvariantWrapperTransform(transform); + } }; BR_REGISTER(Transform, DistributeTemplateTransform)