Commit b78b07b23286e0067037be0b65dc9422983a6dee

Authored by Charles Otto
1 parent 3389c2e8

Drop additional parameter to store, instead introduce Transform::simplify

Instead of having a parameter to force serialization of loadStores,
introduce a recursive method for simplifiying transform trees. Transforms
which are only useful during load/training can now remove themselves from
the tree via Transform * simplify, returning e.g. their child transform
instead of themselves when possible.

This avoids the issue of LoadStore transforms refusing to serialize
themselves onto an input stream during multi-process enrollment, since
they are just removed from the tree.
openbr/core/core.cpp
@@ -33,6 +33,7 @@ struct AlgorithmCore @@ -33,6 +33,7 @@ struct AlgorithmCore
33 }; 33 };
34 34
35 QSharedPointer<Transform> transform; 35 QSharedPointer<Transform> transform;
  36 + QSharedPointer<Transform> simplifiedTransform;
36 QSharedPointer<Transform> comparison; 37 QSharedPointer<Transform> comparison;
37 QSharedPointer<Distance> distance; 38 QSharedPointer<Distance> distance;
38 QSharedPointer<Transform> progressCounter; 39 QSharedPointer<Transform> progressCounter;
@@ -82,6 +83,8 @@ struct AlgorithmCore @@ -82,6 +83,8 @@ struct AlgorithmCore
82 } 83 }
83 84
84 qDebug("Training Time: %s", qPrintable(QtUtils::toTime(Globals->startTime.elapsed()/1000.0f))); 85 qDebug("Training Time: %s", qPrintable(QtUtils::toTime(Globals->startTime.elapsed()/1000.0f)));
  86 + bool junk;
  87 + simplifiedTransform = QSharedPointer<Transform>(transform->simplify(junk));
85 } 88 }
86 89
87 void store(const QString &model) const 90 void store(const QString &model) const
@@ -167,7 +170,8 @@ struct AlgorithmCore @@ -167,7 +170,8 @@ struct AlgorithmCore
167 Gallery *temp = Gallery::make(input); 170 Gallery *temp = Gallery::make(input);
168 qint64 total = temp->totalSize(); 171 qint64 total = temp->totalSize();
169 172
170 - Transform *enroll = transform.data(); 173 + Transform *enroll = simplifiedTransform.data();
  174 +
171 if (multiProcess) 175 if (multiProcess)
172 enroll = wrapTransform(enroll, "ProcessWrapper"); 176 enroll = wrapTransform(enroll, "ProcessWrapper");
173 177
@@ -443,9 +447,10 @@ struct AlgorithmCore @@ -443,9 +447,10 @@ struct AlgorithmCore
443 QString compareRegionDesc; 447 QString compareRegionDesc;
444 QList<Transform *> enrollCompare; 448 QList<Transform *> enrollCompare;
445 enrollCompare.append(comparison.data()); 449 enrollCompare.append(comparison.data());
  450 +
446 // if we have to enroll the row gallery, add that transform to the list 451 // if we have to enroll the row gallery, add that transform to the list
447 if (needEnrollRows) 452 if (needEnrollRows)
448 - enrollCompare.prepend(this->transform.data()); 453 + enrollCompare.prepend(simplifiedTransform.data());
449 454
450 Transform *compareRegionBase = pipeTransforms(enrollCompare); 455 Transform *compareRegionBase = pipeTransforms(enrollCompare);
451 // If in multi-process mode, wrap the enroll+compare structure in a ProcessWrapper. 456 // If in multi-process mode, wrap the enroll+compare structure in a ProcessWrapper.
@@ -523,13 +528,18 @@ private: @@ -523,13 +528,18 @@ private:
523 528
524 void init(const QString &description) 529 void init(const QString &description)
525 { 530 {
526 - if (loadOrExpand(description)) 531 + bool junk;
  532 +
  533 + if (loadOrExpand(description)) {
  534 + simplifiedTransform = QSharedPointer<Transform>(transform->simplify(junk));
527 return; 535 return;
  536 + }
528 537
529 // check if the description is an abbreviation or model file with additional arguments supplied 538 // check if the description is an abbreviation or model file with additional arguments supplied
530 File parsed("."+description); 539 File parsed("."+description);
531 if (loadOrExpand(parsed.suffix())) { 540 if (loadOrExpand(parsed.suffix())) {
532 applyAdditionalProperties(parsed, transform.data()); 541 applyAdditionalProperties(parsed, transform.data());
  542 + simplifiedTransform = QSharedPointer<Transform>(transform->simplify(junk));
533 return; 543 return;
534 } 544 }
535 545
@@ -541,6 +551,8 @@ private: @@ -541,6 +551,8 @@ private:
541 551
542 //! [Creating the template generation and comparison methods] 552 //! [Creating the template generation and comparison methods]
543 transform = QSharedPointer<Transform>(Transform::make(words[0], NULL)); 553 transform = QSharedPointer<Transform>(Transform::make(words[0], NULL));
  554 + simplifiedTransform = QSharedPointer<Transform>(transform->simplify(junk));
  555 +
544 if (words.size() > 1) { 556 if (words.size() > 1) {
545 if (!compareTransform) { 557 if (!compareTransform) {
546 distance = QSharedPointer<Distance>(Distance::make(words[1], NULL)); 558 distance = QSharedPointer<Distance>(Distance::make(words[1], NULL));
openbr/core/eval.cpp
@@ -81,6 +81,8 @@ static cv::Mat constructMatchingMask(const cv::Mat &amp;scores, const FileList &amp;targ @@ -81,6 +81,8 @@ static cv::Mat constructMatchingMask(const cv::Mat &amp;scores, const FileList &amp;targ
81 // otherwise, we fail 81 // otherwise, we fail
82 else 82 else
83 qFatal("Unable to construct mask for %d by %d score matrix from %d element query set, and %d element target set ", scores.rows, scores.cols, query.length(), target.length()); 83 qFatal("Unable to construct mask for %d by %d score matrix from %d element query set, and %d element target set ", scores.rows, scores.cols, query.length(), target.length());
  84 +
  85 + return cv::Mat();
84 } 86 }
85 87
86 float Evaluate(const cv::Mat &scores, const FileList &target, const FileList &query, const QString &csv, int partition) 88 float Evaluate(const cv::Mat &scores, const FileList &target, const FileList &query, const QString &csv, int partition)
openbr/openbr_plugin.cpp
@@ -649,7 +649,7 @@ QString Object::description(bool expanded) @@ -649,7 +649,7 @@ QString Object::description(bool expanded)
649 return objectName() + (argumentString.isEmpty() ? "" : ("(" + argumentString + ")")); 649 return objectName() + (argumentString.isEmpty() ? "" : ("(" + argumentString + ")"));
650 } 650 }
651 651
652 -void Object::store(QDataStream &stream, bool force) const 652 +void Object::store(QDataStream &stream) const
653 { 653 {
654 // Start from 1 to skip QObject::objectName 654 // Start from 1 to skip QObject::objectName
655 for (int i=1; i<metaObject()->propertyCount(); i++) { 655 for (int i=1; i<metaObject()->propertyCount(); i++) {
@@ -660,14 +660,14 @@ void Object::store(QDataStream &amp;stream, bool force) const @@ -660,14 +660,14 @@ void Object::store(QDataStream &amp;stream, bool force) const
660 const QString type = property.typeName(); 660 const QString type = property.typeName();
661 if (type == "QList<br::Transform*>") { 661 if (type == "QList<br::Transform*>") {
662 foreach (Transform *transform, property.read(this).value< QList<Transform*> >()) 662 foreach (Transform *transform, property.read(this).value< QList<Transform*> >())
663 - transform->store(stream, force); 663 + transform->store(stream);
664 } else if (type == "QList<br::Distance*>") { 664 } else if (type == "QList<br::Distance*>") {
665 foreach (Distance *distance, property.read(this).value< QList<Distance*> >()) 665 foreach (Distance *distance, property.read(this).value< QList<Distance*> >())
666 - distance->store(stream, force); 666 + distance->store(stream);
667 } else if (type == "br::Transform*") { 667 } else if (type == "br::Transform*") {
668 - property.read(this).value<Transform*>()->store(stream, force); 668 + property.read(this).value<Transform*>()->store(stream);
669 } else if (type == "br::Distance*") { 669 } else if (type == "br::Distance*") {
670 - property.read(this).value<Distance*>()->store(stream, force); 670 + property.read(this).value<Distance*>()->store(stream);
671 } else if (type == "bool") { 671 } else if (type == "bool") {
672 stream << property.read(this).toBool(); 672 stream << property.read(this).toBool();
673 } else if (type == "int") { 673 } else if (type == "int") {
openbr/openbr_plugin.h
@@ -589,14 +589,14 @@ public: @@ -589,14 +589,14 @@ public:
589 File file; /*!< \brief The file used to construct the plugin. */ 589 File file; /*!< \brief The file used to construct the plugin. */
590 590
591 virtual void init() {} /*!< \brief Overload this function instead of the default constructor to initialize the derived class. It should be safe to call this function multiple times. */ 591 virtual void init() {} /*!< \brief Overload this function instead of the default constructor to initialize the derived class. It should be safe to call this function multiple times. */
592 - virtual void store(QDataStream &stream, bool force = false) const; /*!< \brief Serialize the object. If force is true, classes must serialize directly on the stream not to e.g. a separate file. */ 592 + virtual void store(QDataStream &stream) const; /*!< \brief Serialize the object. If force is true, classes must serialize directly on the stream not to e.g. a separate file. */
593 virtual void load(QDataStream &stream); /*!< \brief Deserialize the object. Default implementation calls init() after deserialization. */ 593 virtual void load(QDataStream &stream); /*!< \brief Deserialize the object. Default implementation calls init() after deserialization. */
594 594
595 /*!< \brief Serialize an object created via the plugin system, including the string used to build the base object, allowing re-creation of the object without knowledge of its base string*/ 595 /*!< \brief Serialize an object created via the plugin system, including the string used to build the base object, allowing re-creation of the object without knowledge of its base string*/
596 virtual void serialize(QDataStream &stream, bool force) 596 virtual void serialize(QDataStream &stream, bool force)
597 { 597 {
598 stream << description(force); 598 stream << description(force);
599 - store(stream, force); 599 + store(stream);
600 } 600 }
601 601
602 QStringList parameters() const; /*!< \brief A string describing the parameters the object takes. */ 602 QStringList parameters() const; /*!< \brief A string describing the parameters the object takes. */
@@ -1290,6 +1290,8 @@ public: @@ -1290,6 +1290,8 @@ public:
1290 return res; 1290 return res;
1291 } 1291 }
1292 1292
  1293 + virtual Transform * simplify(bool & newTransform) { newTransform = false; return this; }
  1294 +
1293 protected: 1295 protected:
1294 Transform(bool independent = true, bool trainable = true); /*!< \brief Construct a transform. */ 1296 Transform(bool independent = true, bool trainable = true); /*!< \brief Construct a transform. */
1295 inline Transform *make(const QString &description) { return make(description, this); } /*!< \brief Make a subtransform. */ 1297 inline Transform *make(const QString &description) { return make(description, this); } /*!< \brief Make a subtransform. */
openbr/plugins/cascade.cpp
@@ -415,7 +415,7 @@ class CascadeTransform : public MetaTransform @@ -415,7 +415,7 @@ class CascadeTransform : public MetaTransform
415 } 415 }
416 416
417 // TODO: Remove this code when ready to break binary compatibility 417 // TODO: Remove this code when ready to break binary compatibility
418 - void store(QDataStream &stream, bool force) const 418 + void store(QDataStream &stream) const
419 { 419 {
420 int size = 1; 420 int size = 1;
421 stream << size; 421 stream << size;
openbr/plugins/cluster.cpp
@@ -69,7 +69,7 @@ class KMeansTransform : public Transform @@ -69,7 +69,7 @@ class KMeansTransform : public Transform
69 reindex(); 69 reindex();
70 } 70 }
71 71
72 - void store(QDataStream &stream, bool force) const 72 + void store(QDataStream &stream) const
73 { 73 {
74 stream << centers; 74 stream << centers;
75 } 75 }
@@ -131,7 +131,7 @@ class KNNTransform : public Transform @@ -131,7 +131,7 @@ class KNNTransform : public Transform
131 dst.file.set("Nearest", gallery[sortedScores[0].second].file.name); 131 dst.file.set("Nearest", gallery[sortedScores[0].second].file.name);
132 } 132 }
133 133
134 - void store(QDataStream &stream, bool force) const 134 + void store(QDataStream &stream) const
135 { 135 {
136 stream << gallery; 136 stream << gallery;
137 } 137 }
@@ -196,7 +196,7 @@ class RandomCentroidsTransform : public Transform @@ -196,7 +196,7 @@ class RandomCentroidsTransform : public Transform
196 reindex(); 196 reindex();
197 } 197 }
198 198
199 - void store(QDataStream &stream, bool force) const 199 + void store(QDataStream &stream) const
200 { 200 {
201 stream << centers; 201 stream << centers;
202 } 202 }
openbr/plugins/distance.cpp
@@ -251,13 +251,14 @@ private: @@ -251,13 +251,14 @@ private:
251 default: 251 default:
252 qFatal("Invalid operation."); 252 qFatal("Invalid operation.");
253 } 253 }
  254 + return 0;
254 } 255 }
255 256
256 - void store(QDataStream &stream, bool force) const 257 + void store(QDataStream &stream) const
257 { 258 {
258 stream << distances.size(); 259 stream << distances.size();
259 foreach (Distance *distance, distances) 260 foreach (Distance *distance, distances)
260 - distance->store(stream, force); 261 + distance->store(stream);
261 } 262 }
262 263
263 void load(QDataStream &stream) 264 void load(QDataStream &stream)
@@ -328,9 +329,9 @@ class NegativeLogPlusOneDistance : public Distance @@ -328,9 +329,9 @@ class NegativeLogPlusOneDistance : public Distance
328 return -log(distance->compare(a,b)+1); 329 return -log(distance->compare(a,b)+1);
329 } 330 }
330 331
331 - void store(QDataStream &stream, bool force) const 332 + void store(QDataStream &stream) const
332 { 333 {
333 - distance->store(stream, force); 334 + distance->store(stream);
334 } 335 }
335 336
336 void load(QDataStream &stream) 337 void load(QDataStream &stream)
@@ -488,9 +489,9 @@ class GalleryCompareTransform : public Transform @@ -488,9 +489,9 @@ class GalleryCompareTransform : public Transform
488 gallery = data; 489 gallery = data;
489 } 490 }
490 491
491 - void store(QDataStream &stream, bool force) const 492 + void store(QDataStream &stream) const
492 { 493 {
493 - br::Object::store(stream, force); 494 + br::Object::store(stream);
494 stream << gallery; 495 stream << gallery;
495 } 496 }
496 497
openbr/plugins/eigen3.cpp
@@ -119,7 +119,7 @@ private: @@ -119,7 +119,7 @@ private:
119 outMap = eVecs.transpose() * (inMap - mean); 119 outMap = eVecs.transpose() * (inMap - mean);
120 } 120 }
121 121
122 - void store(QDataStream &stream, bool force) const 122 + void store(QDataStream &stream) const
123 { 123 {
124 stream << keep << drop << whiten << originalRows << mean << eVals << eVecs; 124 stream << keep << drop << whiten << originalRows << mean << eVals << eVecs;
125 } 125 }
@@ -295,9 +295,9 @@ class DFFSTransform : public Transform @@ -295,9 +295,9 @@ class DFFSTransform : public Transform
295 dst.file.set("DFFS", sqrt(pca.residualReconstructionError((*cvtFloat)(src)))); 295 dst.file.set("DFFS", sqrt(pca.residualReconstructionError((*cvtFloat)(src))));
296 } 296 }
297 297
298 - void store(QDataStream &stream, bool force) const 298 + void store(QDataStream &stream) const
299 { 299 {
300 - pca.store(stream, force); 300 + pca.store(stream);
301 } 301 }
302 302
303 void load(QDataStream &stream) 303 void load(QDataStream &stream)
@@ -525,7 +525,7 @@ class LDATransform : public Transform @@ -525,7 +525,7 @@ class LDATransform : public Transform
525 dst.m().at<float>(0,0) = dst.m().at<float>(0,0) / stdDev; 525 dst.m().at<float>(0,0) = dst.m().at<float>(0,0) / stdDev;
526 } 526 }
527 527
528 - void store(QDataStream &stream, bool force) const 528 + void store(QDataStream &stream) const
529 { 529 {
530 stream << pcaKeep; 530 stream << pcaKeep;
531 stream << directLDA; 531 stream << directLDA;
@@ -631,10 +631,10 @@ class SparseLDATransform : public Transform @@ -631,10 +631,10 @@ class SparseLDATransform : public Transform
631 ldaSparse.project(Template(src.file, inSelect), dst); 631 ldaSparse.project(Template(src.file, inSelect), dst);
632 } 632 }
633 633
634 - void store(QDataStream &stream, bool force) const 634 + void store(QDataStream &stream) const
635 { 635 {
636 stream << pcaKeep; 636 stream << pcaKeep;
637 - ldaSparse.store(stream, force); 637 + ldaSparse.store(stream);
638 stream << dimsOut; 638 stream << dimsOut;
639 stream << selections; 639 stream << selections;
640 } 640 }
openbr/plugins/frames.cpp
@@ -43,7 +43,7 @@ private: @@ -43,7 +43,7 @@ private:
43 buffer.clear(); 43 buffer.clear();
44 } 44 }
45 45
46 - void store(QDataStream &stream, bool force) const 46 + void store(QDataStream &stream) const
47 { 47 {
48 (void) stream; 48 (void) stream;
49 } 49 }
openbr/plugins/independent.cpp
@@ -94,6 +94,12 @@ class DownsampleTrainingTransform : public Transform @@ -94,6 +94,12 @@ class DownsampleTrainingTransform : public Transform
94 BR_PROPERTY(QStringList, subjects, QStringList()) 94 BR_PROPERTY(QStringList, subjects, QStringList())
95 95
96 96
  97 + Transform *simplify(bool &newTForm)
  98 + {
  99 + Transform * res = transform->simplify(newTForm);
  100 + return res;
  101 + }
  102 +
97 void project(const Template &src, Template &dst) const 103 void project(const Template &src, Template &dst) const
98 { 104 {
99 transform->project(src,dst); 105 transform->project(src,dst);
@@ -145,6 +151,54 @@ class IndependentTransform : public MetaTransform @@ -145,6 +151,54 @@ class IndependentTransform : public MetaTransform
145 return true; 151 return true;
146 } 152 }
147 153
  154 + Transform * simplify(bool & newTransform)
  155 + {
  156 + newTransform = false;
  157 + bool newChild = false;
  158 + Transform * temp = transform->simplify(newChild);
  159 + if (temp == transform) {
  160 + return this;
  161 + }
  162 + IndependentTransform* indep = new IndependentTransform();
  163 + indep->transform = temp;
  164 +
  165 + bool subInd = false;
  166 + IndependentTransform * test = dynamic_cast<IndependentTransform *> (temp);
  167 + if (test) {
  168 + // child was independent? this changes things...
  169 + subInd = true;
  170 + indep->transform = test->transform;
  171 + for (int i=0; i < transforms.size(); i++) {
  172 + bool newThing = false;
  173 + IndependentTransform * probe = dynamic_cast<IndependentTransform *> (transforms[i]->simplify(newThing));
  174 + indep->transforms.append(probe->transform);
  175 + if (newThing)
  176 + probe->setParent(indep);
  177 + }
  178 + indep->file = indep->transform->file;
  179 + indep->trainable = indep->transform->trainable;
  180 + indep->setObjectName(indep->transform->objectName());
  181 +
  182 + return indep;
  183 + }
  184 +
  185 + if (newChild)
  186 + indep->transform->setParent(indep);
  187 +
  188 + for (int i=0; i < transforms.size();i++) {
  189 + bool subTform = false;
  190 + indep->transforms.append(transforms[i]->simplify(subTform));
  191 + if (subTform)
  192 + indep->transforms[i]->setParent(indep);
  193 + }
  194 +
  195 + indep->file = indep->transform->file;
  196 + indep->trainable = indep->transform->trainable;
  197 + indep->setObjectName(indep->transform->objectName());
  198 +
  199 + return indep;
  200 + }
  201 +
148 void init() 202 void init()
149 { 203 {
150 transforms.clear(); 204 transforms.clear();
@@ -230,12 +284,12 @@ class IndependentTransform : public MetaTransform @@ -230,12 +284,12 @@ class IndependentTransform : public MetaTransform
230 } 284 }
231 } 285 }
232 286
233 - void store(QDataStream &stream, bool force) const 287 + void store(QDataStream &stream) const
234 { 288 {
235 const int size = transforms.size(); 289 const int size = transforms.size();
236 stream << size; 290 stream << size;
237 for (int i=0; i<size; i++) 291 for (int i=0; i<size; i++)
238 - transforms[i]->store(stream, force); 292 + transforms[i]->store(stream);
239 } 293 }
240 294
241 void load(QDataStream &stream) 295 void load(QDataStream &stream)
@@ -296,10 +350,10 @@ class SingletonTransform : public MetaTransform @@ -296,10 +350,10 @@ class SingletonTransform : public MetaTransform
296 transform->project(src, dst); 350 transform->project(src, dst);
297 } 351 }
298 352
299 - void store(QDataStream &stream, bool force) const 353 + void store(QDataStream &stream) const
300 { 354 {
301 if (transform->parent() == this) 355 if (transform->parent() == this)
302 - transform->store(stream, force); 356 + transform->store(stream);
303 } 357 }
304 358
305 void load(QDataStream &stream) 359 void load(QDataStream &stream)
openbr/plugins/integral.cpp
@@ -251,12 +251,12 @@ class RecursiveIntegralSamplerTransform : public Transform @@ -251,12 +251,12 @@ class RecursiveIntegralSamplerTransform : public Transform
251 } 251 }
252 } 252 }
253 253
254 - void store(QDataStream &stream, bool force) const 254 + void store(QDataStream &stream) const
255 { 255 {
256 - transform->store(stream, force); 256 + transform->store(stream);
257 stream << (subTransform != NULL); 257 stream << (subTransform != NULL);
258 if (subTransform != NULL) 258 if (subTransform != NULL)
259 - subTransform->store(stream, force); 259 + subTransform->store(stream);
260 } 260 }
261 261
262 void load(QDataStream &stream) 262 void load(QDataStream &stream)
openbr/plugins/landmarks.cpp
@@ -125,7 +125,7 @@ class ProcrustesTransform : public Transform @@ -125,7 +125,7 @@ class ProcrustesTransform : public Transform
125 } 125 }
126 } 126 }
127 127
128 - void store(QDataStream &stream, bool force) const 128 + void store(QDataStream &stream) const
129 { 129 {
130 stream << meanShape; 130 stream << meanShape;
131 } 131 }
@@ -299,7 +299,7 @@ class ProcrustesAlignTransform : public Transform @@ -299,7 +299,7 @@ class ProcrustesAlignTransform : public Transform
299 dst.file.set("ProcrustesBound", QRectF(0, 0, width + 2 * padding, (qRound(width / aspectRatio) + 2 * padding))); 299 dst.file.set("ProcrustesBound", QRectF(0, 0, width + 2 * padding, (qRound(width / aspectRatio) + 2 * padding)));
300 } 300 }
301 301
302 - void store(QDataStream &stream, bool force) const 302 + void store(QDataStream &stream) const
303 { 303 {
304 stream << referenceShape; 304 stream << referenceShape;
305 stream << minX; 305 stream << minX;
openbr/plugins/meta.cpp
@@ -487,10 +487,10 @@ class LoadStoreTransform : public MetaTransform @@ -487,10 +487,10 @@ class LoadStoreTransform : public MetaTransform
487 BR_PROPERTY(QString, description2, "Identity") 487 BR_PROPERTY(QString, description2, "Identity")
488 BR_PROPERTY(QString, fileName, QString()) 488 BR_PROPERTY(QString, fileName, QString())
489 489
  490 +public:
490 Transform *transform; 491 Transform *transform;
491 QString baseName; 492 QString baseName;
492 493
493 -public:  
494 LoadStoreTransform() : transform(NULL) {} 494 LoadStoreTransform() : transform(NULL) {}
495 495
496 QString description(bool expanded = false) 496 QString description(bool expanded = false)
@@ -500,6 +500,12 @@ public: @@ -500,6 +500,12 @@ public:
500 return br::Object::description(expanded); 500 return br::Object::description(expanded);
501 } 501 }
502 502
  503 + Transform * simplify(bool & newTForm)
  504 + {
  505 + Transform * res = transform->simplify(newTForm);
  506 + return res;
  507 + }
  508 +
503 bool setPropertyRecursive(const QString &name, QVariant value) 509 bool setPropertyRecursive(const QString &name, QVariant value)
504 { 510 {
505 if (br::Object::setPropertyRecursive(name, value)) 511 if (br::Object::setPropertyRecursive(name, value))
@@ -508,22 +514,15 @@ public: @@ -508,22 +514,15 @@ public:
508 } 514 }
509 private: 515 private:
510 516
511 - virtual void store(QDataStream &stream, bool force = false) const  
512 - {  
513 - if (force) {  
514 - transform->store(stream, force);  
515 - }  
516 -  
517 - br::Object::store(stream, false);  
518 - }  
519 -  
520 void init() 517 void init()
521 { 518 {
522 if (transform != NULL) return; 519 if (transform != NULL) return;
523 if (fileName.isEmpty()) baseName = QRegExp("^[a-zA-Z0-9]+$").exactMatch(description2) ? description2 : QtUtils::shortTextHash(description2); 520 if (fileName.isEmpty()) baseName = QRegExp("^[a-zA-Z0-9]+$").exactMatch(description2) ? description2 : QtUtils::shortTextHash(description2);
524 else baseName = fileName; 521 else baseName = fileName;
525 - if (!tryLoad()) transform = make(description2);  
526 - else trainable = false; 522 + if (!tryLoad())
  523 + transform = make(description2);
  524 + else
  525 + trainable = false;
527 } 526 }
528 527
529 bool timeVarying() const 528 bool timeVarying() const
openbr/plugins/normalize.cpp
@@ -167,7 +167,7 @@ private: @@ -167,7 +167,7 @@ private:
167 divide(dst, a, dst); 167 divide(dst, a, dst);
168 } 168 }
169 169
170 - void store(QDataStream &stream, bool force) const 170 + void store(QDataStream &stream) const
171 { 171 {
172 stream << a << b; 172 stream << a << b;
173 } 173 }
@@ -256,7 +256,7 @@ class RowWiseMeanCenterTransform : public Transform @@ -256,7 +256,7 @@ class RowWiseMeanCenterTransform : public Transform
256 dst = m; 256 dst = m;
257 } 257 }
258 258
259 - void store(QDataStream &stream, bool force) const 259 + void store(QDataStream &stream) const
260 { 260 {
261 stream << mean; 261 stream << mean;
262 } 262 }
openbr/plugins/openbr_internal.h
@@ -19,7 +19,7 @@ protected: @@ -19,7 +19,7 @@ protected:
19 private: 19 private:
20 Transform *clone() const { return const_cast<UntrainableTransform*>(this); } 20 Transform *clone() const { return const_cast<UntrainableTransform*>(this); }
21 void train(const TemplateList &data) { (void) data; } 21 void train(const TemplateList &data) { (void) data; }
22 - void store(QDataStream &stream, bool force) const { (void) stream; (void) force; } 22 + void store(QDataStream &stream) const { (void) stream; }
23 void load(QDataStream &stream) { (void) stream; } 23 void load(QDataStream &stream) { (void) stream; }
24 }; 24 };
25 25
@@ -201,6 +201,33 @@ public: @@ -201,6 +201,33 @@ public:
201 this->trainable = transform->trainable; 201 this->trainable = transform->trainable;
202 } 202 }
203 203
  204 + virtual Transform * simplify(bool & newTransform)
  205 + {
  206 + newTransform = false;
  207 + bool newChild = false;
  208 + Transform * temp = transform->simplify(newTransform);
  209 + if (temp == transform)
  210 + return this;
  211 +
  212 + if (!temp)
  213 + return NULL;
  214 +
  215 + // else make a copy to point at the new transform
  216 + Transform * child = transform;
  217 + transform = NULL;
  218 + WrapperTransform *output = dynamic_cast<WrapperTransform *>(Transform::make(description(), NULL));
  219 + transform = child;
  220 +
  221 + output->transform = temp;
  222 +
  223 + if (newChild)
  224 + temp->setParent(output);
  225 +
  226 + newTransform = true;
  227 + return output;
  228 + }
  229 +
  230 +
204 bool setPropertyRecursive(const QString &name, QVariant value) 231 bool setPropertyRecursive(const QString &name, QVariant value)
205 { 232 {
206 if (br::Object::setPropertyRecursive(name, value)) 233 if (br::Object::setPropertyRecursive(name, value))
@@ -220,21 +247,10 @@ public: @@ -220,21 +247,10 @@ public:
220 return this; 247 return this;
221 } 248 }
222 newTransform = true; 249 newTransform = true;
223 -  
224 - QString name = metaObject()->className();  
225 - name.replace("Transform","");  
226 - name += "(Identity";  
227 -  
228 - QStringList arguments = this->arguments();  
229 - if (!arguments.isEmpty()) {  
230 - name += ",";  
231 - name += this->arguments().join(",");  
232 - }  
233 -  
234 - name += ")";  
235 - name.replace("br::","");  
236 -  
237 - WrapperTransform *output = dynamic_cast<WrapperTransform *>(Transform::make(name, NULL)); 250 + Transform * temp = transform;
  251 + transform = NULL;
  252 + WrapperTransform *output = dynamic_cast<WrapperTransform *>(Transform::make(description(), NULL));
  253 + transform = temp;
238 254
239 if (output == NULL) 255 if (output == NULL)
240 qFatal("Dynamic cast failed!"); 256 qFatal("Dynamic cast failed!");
@@ -309,21 +325,10 @@ public: @@ -309,21 +325,10 @@ public:
309 } 325 }
310 newTransform = true; 326 newTransform = true;
311 327
312 - QString name = metaObject()->className();  
313 -  
314 - name.replace("Transform","");  
315 - name += "([]";  
316 -  
317 - QStringList arguments = this->arguments();  
318 - if (!arguments.isEmpty()) {  
319 - name += ",";  
320 - name += this->arguments().join(",");  
321 - }  
322 -  
323 - name += ")";  
324 - name.replace("br::","");  
325 -  
326 - CompositeTransform *output = dynamic_cast<CompositeTransform *>(Transform::make(name, NULL)); 328 + QList<Transform *> temp = transforms;
  329 + transforms = QList<Transform *>();
  330 + CompositeTransform *output = dynamic_cast<CompositeTransform *>(Transform::make(description(), NULL));
  331 + transforms = temp;
327 332
328 if (output == NULL) 333 if (output == NULL)
329 qFatal("Dynamic cast failed!"); 334 qFatal("Dynamic cast failed!");
@@ -342,6 +347,51 @@ public: @@ -342,6 +347,51 @@ public:
342 return output; 347 return output;
343 } 348 }
344 349
  350 + virtual Transform * simplify(bool & newTransform)
  351 + {
  352 + newTransform = false;
  353 + QList<Transform *> newTransforms;
  354 + bool anyNew = false;
  355 +
  356 + QList<bool> newChildren;
  357 + for (int i=0; i < transforms.size();i++)
  358 + {
  359 + bool newChild = false;
  360 + Transform * temp = transforms[i]->simplify(newChild);
  361 + if (temp == NULL) {
  362 + anyNew = true;
  363 + continue;
  364 + }
  365 + newTransforms.append(temp);
  366 + newChildren.append(newChild);
  367 + if (temp != transforms[i])
  368 + anyNew = true;
  369 + }
  370 +
  371 + if (newTransforms.empty() )
  372 + return NULL;
  373 +
  374 + if (!anyNew)
  375 + return this;
  376 +
  377 + // make a copy of the current object, with empty transforms
  378 + QList<Transform *> children = transforms;
  379 + transforms = QList<Transform *> ();
  380 + CompositeTransform *output = dynamic_cast<CompositeTransform *>(Transform::make(description(false), NULL));
  381 + transforms = children;
  382 +
  383 + output->transforms = newTransforms;
  384 + for (int i=0;i < newChildren.size();i++)
  385 + {
  386 + if (newChildren[i])
  387 + output->transforms[i]->setParent(output);
  388 + }
  389 + output->init();
  390 +
  391 + newTransform = true;
  392 + return output;
  393 + }
  394 +
345 bool setPropertyRecursive(const QString &name, QVariant value) 395 bool setPropertyRecursive(const QString &name, QVariant value)
346 { 396 {
347 if (br::Object::setPropertyRecursive(name, value)) 397 if (br::Object::setPropertyRecursive(name, value))
openbr/plugins/pp5.cpp
@@ -510,9 +510,9 @@ class PP5GalleryTransform: public UntrainableMetaTransform @@ -510,9 +510,9 @@ class PP5GalleryTransform: public UntrainableMetaTransform
510 gallery = data; 510 gallery = data;
511 } 511 }
512 512
513 - void store(QDataStream &stream, bool force) const 513 + void store(QDataStream &stream) const
514 { 514 {
515 - br::Object::store(stream, force); 515 + br::Object::store(stream);
516 stream << gallery; 516 stream << gallery;
517 } 517 }
518 518
openbr/plugins/process.cpp
@@ -578,6 +578,7 @@ class ProcessWrapperTransform : public WrapperTransform @@ -578,6 +578,7 @@ class ProcessWrapperTransform : public WrapperTransform
578 578
579 QStringList argumentList; 579 QStringList argumentList;
580 // We serialize and transmit the transform directly, so algorithm doesn't matter. 580 // We serialize and transmit the transform directly, so algorithm doesn't matter.
  581 + argumentList.append("-quiet");
581 argumentList.append("-algorithm"); 582 argumentList.append("-algorithm");
582 argumentList.append("Identity"); 583 argumentList.append("Identity");
583 if (!Globals->path.isEmpty()) { 584 if (!Globals->path.isEmpty()) {
openbr/plugins/quality.cpp
@@ -62,9 +62,9 @@ class ImpostorUniquenessMeasureTransform : public Transform @@ -62,9 +62,9 @@ class ImpostorUniquenessMeasureTransform : public Transform
62 dst.file.set("Impostor_Uniqueness_Measure_Bin", ium < mean-stddev ? 0 : (ium < mean+stddev ? 1 : 2)); 62 dst.file.set("Impostor_Uniqueness_Measure_Bin", ium < mean-stddev ? 0 : (ium < mean+stddev ? 1 : 2));
63 } 63 }
64 64
65 - void store(QDataStream &stream, bool force) const 65 + void store(QDataStream &stream) const
66 { 66 {
67 - distance->store(stream, force); 67 + distance->store(stream);
68 stream << mean << stddev << impostors; 68 stream << mean << stddev << impostors;
69 } 69 }
70 70
@@ -199,9 +199,9 @@ class MatchProbabilityDistance : public Distance @@ -199,9 +199,9 @@ class MatchProbabilityDistance : public Distance
199 return mp(score, gaussian); 199 return mp(score, gaussian);
200 } 200 }
201 201
202 - void store(QDataStream &stream, bool force) const 202 + void store(QDataStream &stream) const
203 { 203 {
204 - distance->store(stream, force); 204 + distance->store(stream);
205 stream << mp; 205 stream << mp;
206 } 206 }
207 207
@@ -264,9 +264,9 @@ class ZScoreDistance : public Distance @@ -264,9 +264,9 @@ class ZScoreDistance : public Distance
264 return score; 264 return score;
265 } 265 }
266 266
267 - void store(QDataStream &stream, bool force) const 267 + void store(QDataStream &stream) const
268 { 268 {
269 - distance->store(stream, force); 269 + distance->store(stream);
270 stream << min << max << mean << stddev; 270 stream << min << max << mean << stddev;
271 } 271 }
272 272
@@ -335,11 +335,11 @@ class HeatMapDistance : public Distance @@ -335,11 +335,11 @@ class HeatMapDistance : public Distance
335 } 335 }
336 } 336 }
337 337
338 - void store(QDataStream &stream, bool force) const 338 + void store(QDataStream &stream) const
339 { 339 {
340 stream << distances.size(); 340 stream << distances.size();
341 foreach (Distance *distance, distances) 341 foreach (Distance *distance, distances)
342 - distance->store(stream, force); 342 + distance->store(stream);
343 } 343 }
344 344
345 void load(QDataStream &stream) 345 void load(QDataStream &stream)
openbr/plugins/quantize.cpp
@@ -99,7 +99,7 @@ class HistEqQuantizationTransform : public Transform @@ -99,7 +99,7 @@ class HistEqQuantizationTransform : public Transform
99 } 99 }
100 } 100 }
101 101
102 - void store(QDataStream &stream, bool force) const 102 + void store(QDataStream &stream) const
103 { 103 {
104 stream << thresholds; 104 stream << thresholds;
105 } 105 }
@@ -174,7 +174,7 @@ class BayesianQuantizationDistance : public Distance @@ -174,7 +174,7 @@ class BayesianQuantizationDistance : public Distance
174 return likelihood; 174 return likelihood;
175 } 175 }
176 176
177 - void store(QDataStream &stream, bool force) const 177 + void store(QDataStream &stream) const
178 { 178 {
179 stream << loglikelihoods; 179 stream << loglikelihoods;
180 } 180 }
@@ -527,7 +527,7 @@ private: @@ -527,7 +527,7 @@ private:
527 dst.m().at<uchar>(0,sizeof(quint16)+i) = getIndex(m.colRange(max(0, i*step-offset), (i+1)*step-offset), centers[i]); 527 dst.m().at<uchar>(0,sizeof(quint16)+i) = getIndex(m.colRange(max(0, i*step-offset), (i+1)*step-offset), centers[i]);
528 } 528 }
529 529
530 - void store(QDataStream &stream, bool force) const 530 + void store(QDataStream &stream) const
531 { 531 {
532 stream << index << centers << ProductQuantizationLUTs[index]; 532 stream << index << centers << ProductQuantizationLUTs[index];
533 } 533 }
openbr/plugins/quantize2.cpp
@@ -104,7 +104,7 @@ class BayesianQuantizationTransform : public Transform @@ -104,7 +104,7 @@ class BayesianQuantizationTransform : public Transform
104 } 104 }
105 } 105 }
106 106
107 - void store(QDataStream &stream, bool force) const 107 + void store(QDataStream &stream) const
108 { 108 {
109 stream << thresholds; 109 stream << thresholds;
110 } 110 }
openbr/plugins/random.cpp
@@ -78,7 +78,7 @@ class RndSubspaceTransform : public Transform @@ -78,7 +78,7 @@ class RndSubspaceTransform : public Transform
78 remap(src, dst, map, Mat(), INTER_NEAREST); 78 remap(src, dst, map, Mat(), INTER_NEAREST);
79 } 79 }
80 80
81 - void store(QDataStream &stream, bool force) const 81 + void store(QDataStream &stream) const
82 { 82 {
83 stream << fraction << weighted << map; 83 stream << fraction << weighted << map;
84 } 84 }
openbr/plugins/slidingwindow.cpp
@@ -79,9 +79,9 @@ private: @@ -79,9 +79,9 @@ private:
79 } 79 }
80 } 80 }
81 81
82 - void store(QDataStream &stream, bool force) const 82 + void store(QDataStream &stream) const
83 { 83 {
84 - transform->store(stream, force); 84 + transform->store(stream);
85 stream << windowHeight; 85 stream << windowHeight;
86 } 86 }
87 87
@@ -289,9 +289,9 @@ private: @@ -289,9 +289,9 @@ private:
289 } 289 }
290 } 290 }
291 291
292 - void store(QDataStream &stream, bool force) const 292 + void store(QDataStream &stream) const
293 { 293 {
294 - transform->store(stream, force); 294 + transform->store(stream);
295 stream << aspectRatio << windowHeight; 295 stream << aspectRatio << windowHeight;
296 } 296 }
297 void load(QDataStream &stream) 297 void load(QDataStream &stream)
openbr/plugins/svm.cpp
@@ -172,7 +172,7 @@ private: @@ -172,7 +172,7 @@ private:
172 dst.file.set(outputVariable, reverseLookup[prediction]); 172 dst.file.set(outputVariable, reverseLookup[prediction]);
173 } 173 }
174 174
175 - void store(QDataStream &stream, bool force) const 175 + void store(QDataStream &stream) const
176 { 176 {
177 storeSVM(svm, stream); 177 storeSVM(svm, stream);
178 stream << labelMap << reverseLookup; 178 stream << labelMap << reverseLookup;
@@ -270,7 +270,7 @@ private: @@ -270,7 +270,7 @@ private:
270 return svm.predict(delta.reshape(1, 1)); 270 return svm.predict(delta.reshape(1, 1));
271 } 271 }
272 272
273 - void store(QDataStream &stream, bool force) const 273 + void store(QDataStream &stream) const
274 { 274 {
275 storeSVM(svm, stream); 275 storeSVM(svm, stream);
276 } 276 }
openbr/plugins/validate.cpp
@@ -114,11 +114,11 @@ class CrossValidateTransform : public MetaTransform @@ -114,11 +114,11 @@ class CrossValidateTransform : public MetaTransform
114 transforms[partition]->project(src, dst); 114 transforms[partition]->project(src, dst);
115 } 115 }
116 116
117 - void store(QDataStream &stream, bool force) const 117 + void store(QDataStream &stream) const
118 { 118 {
119 stream << transforms.size(); 119 stream << transforms.size();
120 foreach (Transform *transform, transforms) 120 foreach (Transform *transform, transforms)
121 - transform->store(stream, force); 121 + transform->store(stream);
122 } 122 }
123 123
124 void load(QDataStream &stream) 124 void load(QDataStream &stream)