diff --git a/sdk/core/core.cpp b/sdk/core/core.cpp index b5bdefb..8d5f4a3 100644 --- a/sdk/core/core.cpp +++ b/sdk/core/core.cpp @@ -262,6 +262,9 @@ private: QStringList words = QtUtils::parse(description, ':'); if (words.size() > 2) qFatal("Invalid algorithm format."); + words[0].prepend("DistributeTemplate("); + words[0].append(")"); + transform = QSharedPointer(Transform::make(words[0], NULL)); if (words.size() > 1) distance = QSharedPointer(Distance::make(words[1], NULL)); } diff --git a/sdk/openbr_plugin.cpp b/sdk/openbr_plugin.cpp index 5e5956b..7f84972 100644 --- a/sdk/openbr_plugin.cpp +++ b/sdk/openbr_plugin.cpp @@ -1202,10 +1202,8 @@ Transform *Transform::make(QString str, QObject *parent) if (Globals->abbreviations.contains(str)) return make(Globals->abbreviations[str], parent); - { // Check for use of '!' as shorthand for Expand(...) - QStringList words = parse(str, '!'); - if (words.size() > 1) - return make("Expand([" + words.join(",") + "])", parent); + { // Check for use of '!' as shorthand for Expand + str.replace("!","+Expand+"); } { // Check for use of '+' as shorthand for Pipe(...) @@ -1250,17 +1248,6 @@ Transform *Transform::clone() const return clone; } -static void _project(const Transform *transform, const Template *src, Template *dst) -{ - try { - transform->project(*src, *dst); - } catch (...) { - qWarning("Exception triggered when processing %s with transform %s", qPrintable(src->file.flat()), qPrintable(transform->objectName())); - *dst = Template(src->file); - dst->file.set("FTE", true); - } -} - static void _backProject(const Transform *transform, const Template *dst, Template *src) { try { @@ -1273,17 +1260,25 @@ static void _backProject(const Transform *transform, const Template *dst, Templa } + +// Default project(TemplateList) -- call project(template) separately for each input +// template void Transform::project(const TemplateList &src, TemplateList &dst) const { - dst.reserve(src.size()); - for (int i=0; i > futures; - if (Globals->parallelism) futures.reserve(src.size()); - for (int i=0; iparallelism) futures.append(QtConcurrent::run(_project, this, &src[i], &dst[i])); - else _project (this, &src[i], &dst[i]); - if (Globals->parallelism) Globals->trackFutures(futures); + dst.clear(); + + // Project templates derived from a single image, default implementation: project each + // input template to an ouptut template individually. + foreach(const Template & src_template, src) { + dst.append(Template(src_template.file)); + try { + project(src_template, dst.back()); + } catch (...) { + qWarning("Exception triggered when processing %s with transform %s", qPrintable(src_template.file.flat()), qPrintable(objectName())); + dst.back() = Template(src_template.file); + dst.back().file.set("FTE", true); + } + } } void Transform::backProject(const Template &dst, Template &src) const diff --git a/sdk/plugins/gallery.cpp b/sdk/plugins/gallery.cpp index 42253d4..03f2c42 100644 --- a/sdk/plugins/gallery.cpp +++ b/sdk/plugins/gallery.cpp @@ -590,10 +590,10 @@ class dbGallery : public Gallery } QStringList labels = entries.keys(); + qSort(labels); + if (hasFilter && ((labels.size() > numSubjects) || (numSubjects == std::numeric_limits::max()))) std::random_shuffle(labels.begin(), labels.end()); - else - qSort(labels); foreach (const QString &label, labels) { QList entryList = entries[label]; diff --git a/sdk/plugins/meta.cpp b/sdk/plugins/meta.cpp index 7ddd48c..a593563 100644 --- a/sdk/plugins/meta.cpp +++ b/sdk/plugins/meta.cpp @@ -86,66 +86,6 @@ static void incrementStep() } /*! - * \brief Use Expanded after basic calls that take a template list, used to implement ExpandTransform - */ -class ExpandDecorator : public Transform -{ - Q_OBJECT - - Q_PROPERTY(br::Transform* transform READ get_transform WRITE set_transform RESET reset_transform) - BR_PROPERTY(br::Transform*, transform, NULL) - -public: - ExpandDecorator(Transform * input) - { - transform = input; - transform->setParent(this); - file = transform->file; - setObjectName(transform->objectName()); - } - - void train(const TemplateList &data) - { - transform->train(data); - } - - void project(const Template &src, Template &dst) const - { - transform->project(src, dst); - } - - void project(const TemplateList &src, TemplateList &dst) const - { - transform->project(src, dst); - dst = Expanded(dst); - } - - - void projectUpdate(const Template &src, Template &dst) - { - transform->projectUpdate(src, dst); - } - - void projectUpdate(const TemplateList & src, TemplateList & dst) - { - transform->projectUpdate(src, dst); - dst = Expanded(dst); - } - - bool timeVarying() const - { - return transform->timeVarying(); - } - - void finalize(TemplateList & output) - { - transform->finalize(output); - output = Expanded(output); - } - -}; - -/*! * \brief A MetaTransform that aggregates some sub-transforms */ class BR_EXPORT CompositeTransform : public TimeVaryingTransform @@ -291,12 +231,9 @@ protected: // or if parallelism is disabled, handle them sequentially void _project(const TemplateList &src, TemplateList &dst) const { - if (Globals->parallelism < 0) { - dst = src; - foreach (const Transform *f, transforms) - dst >> *f; - } else { - Transform::project(src, dst); + dst = src; + foreach (const Transform *f, transforms) { + dst >> *f; } } @@ -320,40 +257,26 @@ BR_REGISTER(Transform, PipeTransform) /*! * \ingroup transforms - * \brief Transforms in series with expansion step. + * \brief Performs an expansion step on input templatelists * \author Josh Klontz \cite jklontz * - * The source br::Template is given to the first transform and the resulting br::Template is passed to the next transform, etc. - * Each matrix is expanded into its own template between steps. + * Each matrix in an input Template is expanded into its own template. * * \see PipeTransform */ -class ExpandTransform : public PipeTransform +class ExpandTransform : public UntrainableMetaTransform { Q_OBJECT - void init() + virtual void project(const TemplateList &src, TemplateList &dst) const { - for (int i = 0; i < transforms.size(); i++) - { - transforms[i] = new ExpandDecorator(transforms[i]); - } - // Need to call this to set up timevariance correctly, and it won't - // be called automatically - CompositeTransform::init(); + dst = Expanded(src); } -protected: - - // Template list project -- project through transforms sequentially, - // then expand the results, can't use Transform::Project(templateList) since - // we need to expand between tranforms, so actually do need to overload this method - void _project(const TemplateList &src, TemplateList &dst) const + virtual void project(const Template & src, Template & dst) const { - dst = src; - for (int i=0; i> *transforms[i]; - } + qFatal("this has gone bad"); + (void) src; (void) dst; } }; @@ -405,12 +328,12 @@ class ForkTransform : public CompositeTransform { dst = src; dst.reserve(src.size()); - for (int i=0; iprojectUpdate(src, m); if (m.size() != dst.size()) qFatal("TemplateList is of an unexpected size."); - for (int i=0; iparallelism < 0) { - dst.reserve(src.size()); - for (int i=0; iproject(src, m); - if (m.size() != dst.size()) qFatal("TemplateList is of an unexpected size."); - for (int i=0; iproject(src, m); + if (m.size() != dst.size()) qFatal("TemplateList is of an unexpected size."); + for (int i=0; iproject(*src, *dst); +} + + +class DistributeTemplateTransform : public UntrainableMetaTransform +{ + Q_OBJECT + Q_PROPERTY(br::Transform* transform READ get_transform WRITE set_transform RESET reset_transform) + BR_PROPERTY(br::Transform*, transform, NULL) + +public: + + void project(const Template &src, Template &dst) const + { + TemplateList input; + input.append(src); + TemplateList output; + project(input, output); + + if (output.size() != 1) qFatal("output contains more than 1 template"); + else dst = output[0]; + } + + + // For each input template, form a single element TemplateList, push all those + // lists through transform, and form dst by concatenating the results. + // Process the single elemnt templates in parallel if parallelism is enabled. + void project(const TemplateList &src, TemplateList &dst) const + { + // Pre-allocate output for each template + QList output_buffer; + output_buffer.reserve(src.size()); + + // Can't declare this local to the loop because it would go out of scope + QList input_buffer; + input_buffer.reserve(src.size()); + + for (int i =0; i < src.size();i++) { + input_buffer.append(TemplateList()); + output_buffer.append(TemplateList()); + } + + QList< QFuture > futures; + futures.reserve(src.size()); + for (int i=0; iparallelism) + futures.append(QtConcurrent::run(_projectList, transform, &input_buffer[i], &output_buffer[i])); + else + _projectList(transform, &input_buffer[i], &output_buffer[i]); + } + + if (Globals->parallelism) + Globals->trackFutures(futures); + + for (int i=0; i