Commit c6a5dfecbf2a03795fc25f6c334202e285f6d385

Authored by Charles Otto
1 parent a2489d31

In enroll, apply Stream's staging logic to the base algorithm

When setting up the stream in enroll, use the Stream interface's staging logic
on the input algorithm. Making this happen is slightly complex when we don't
particularly have header files, but on the plus side algorithms incorporating
something like Show (e.g. ShowFaceDetection) will not be used as a single
threaded stage in the process.
openbr/core/core.cpp
... ... @@ -131,18 +131,33 @@ struct AlgorithmCore
131 131  
132 132 TemplateList i(TemplateList::fromGallery(input));
133 133  
134   - QString shellDescription = "DirectStream([Identity,ProgressCounter("+QString::number(i.length())+")+GalleryOutput("+gallery.flat()+")+Discard],readMode=DistributeFrames)";
  134 + // Trust me, this makes complete sense.
  135 + // We're just going to make a pipe with a placeholder first transform
  136 + QString pipeDesc = "Identity+ProgressCounter("+QString::number(i.length())+")+GalleryOutput("+gallery.flat()+")+Discard";
  137 + QScopedPointer<Transform> basePipe(Transform::make(pipeDesc,NULL));
135 138  
136   - // Make a stream with a placeholder first transform, and our progress counter/gallery output.
137   - QScopedPointer<Transform> enrollJob(Transform::make(shellDescription, NULL));
138   -
139   - CompositeTransform * downcast = dynamic_cast<CompositeTransform *>(enrollJob.data());
  139 + CompositeTransform * downcast = dynamic_cast<CompositeTransform *>(basePipe.data());
140 140 if (downcast == NULL)
141 141 qFatal("downcast failed?");
142 142  
  143 + // replace that placeholder with the current algorithm
143 144 downcast->transforms[0] = this->transform.data();
  145 +
  146 + // call init on the pipe to collapse the algorithm (if its top level is a pipe)
144 147 downcast->init();
145   - downcast->projectUpdate(i,i);
  148 +
  149 + // Next, we make a Stream (with placeholder transform)
  150 + QString streamDesc = "Stream(Identity, readMode=DistributeFrames)";
  151 + QScopedPointer<Transform> baseStream(Transform::make(streamDesc, NULL));
  152 + WrapperTransform * wrapper = dynamic_cast<WrapperTransform *> (baseStream.data());
  153 +
  154 + // replace that placeholder with the pipe we built
  155 + wrapper->transform = downcast;
  156 +
  157 + // and get the final stream's stages by reinterpreting the pipe. Perfectly straightforward.
  158 + wrapper->init();
  159 +
  160 + wrapper->projectUpdate(i,i);
146 161  
147 162 return i.files();
148 163 }
... ...
openbr/plugins/algorithms.cpp
... ... @@ -38,7 +38,7 @@ class AlgorithmsInitializer : public Initializer
38 38 Globals->abbreviations.insert("MedianFace", "Open!Cascade(FrontalFace)+ASEFEyes+Affine(256,256,0.37,0.45)+Center(Median)");
39 39 Globals->abbreviations.insert("BlurredFaceDetection", "Open+LimitSize(1024)+SkinMask/(Cvt(Gray)+GradientMask)+And+Morph(Erode,16)+LargestConvexArea");
40 40 Globals->abbreviations.insert("DrawFaceDetection", "Open+Cascade(FrontalFace)!ASEFEyes+Draw");
41   - Globals->abbreviations.insert("ShowFaceDetection", "DrawFaceDetection!Show[distribute=false]");
  41 + Globals->abbreviations.insert("ShowFaceDetection", "DrawFaceDetection!Show");
42 42 Globals->abbreviations.insert("OpenBR", "FaceRecognition");
43 43 Globals->abbreviations.insert("GenderEstimation", "GenderClassification");
44 44 Globals->abbreviations.insert("AgeEstimation", "AgeRegression");
... ...
openbr/plugins/openbr_internal.h
... ... @@ -154,6 +154,53 @@ protected:
154 154 }
155 155 };
156 156  
  157 +/*!
  158 + * \brief Interface for transforms that act as decorators of another transform
  159 + */
  160 +class BR_EXPORT WrapperTransform : public TimeVaryingTransform
  161 +{
  162 + Q_OBJECT
  163 +public:
  164 + WrapperTransform(bool independent = true) : TimeVaryingTransform(independent)
  165 + {
  166 + }
  167 +
  168 + Q_PROPERTY(br::Transform *transform READ get_transform WRITE set_transform RESET reset_transform STORED false)
  169 + BR_PROPERTY(br::Transform *, transform, NULL)
  170 +
  171 + bool timeVarying() const { return transform->timeVarying(); }
  172 +
  173 + void project(const Template &src, Template &dst) const
  174 + {
  175 + transform->project(src,dst);
  176 + }
  177 +
  178 + void projectUpdate(const Template &src, Template &dst)
  179 + {
  180 + transform->projectUpdate(src,dst);
  181 + }
  182 + void projectUpdate(const TemplateList & src, TemplateList & dst)
  183 + {
  184 + transform->projectUpdate(src,dst);
  185 + }
  186 +
  187 + void train(const QList<TemplateList> & data)
  188 + {
  189 + transform->train(data);
  190 + }
  191 +
  192 + virtual void finalize(TemplateList & output)
  193 + {
  194 + transform->finalize(output);
  195 + }
  196 +
  197 + void init()
  198 + {
  199 + if (transform)
  200 + this->trainable = transform->trainable;
  201 + }
  202 +
  203 +};
157 204  
158 205 /*!
159 206 * \brief A MetaTransform that aggregates some sub-transforms
... ...
openbr/plugins/stream.cpp
... ... @@ -1013,21 +1013,20 @@ QMutex DirectStreamTransform::poolsAccess;
1013 1013  
1014 1014 BR_REGISTER(Transform, DirectStreamTransform)
1015 1015  
1016   -;
1017   -
1018   -class StreamTransform : public TimeVaryingTransform
  1016 +class StreamTransform : public WrapperTransform
1019 1017 {
1020 1018 Q_OBJECT
1021 1019  
1022 1020 public:
1023   - StreamTransform() : TimeVaryingTransform(false)
  1021 + StreamTransform() : WrapperTransform(false)
1024 1022 {
1025 1023 }
1026 1024  
1027   - Q_PROPERTY(br::Transform *transform READ get_transform WRITE set_transform RESET reset_transform STORED false)
1028 1025 Q_PROPERTY(int activeFrames READ get_activeFrames WRITE set_activeFrames RESET reset_activeFrames)
1029   - BR_PROPERTY(br::Transform *, transform, NULL)
  1026 + Q_PROPERTY(br::DirectStreamTransform::StreamModes readMode READ get_readMode WRITE set_readMode RESET reset_readMode)
  1027 +
1030 1028 BR_PROPERTY(int, activeFrames, 100)
  1029 + BR_PROPERTY(br::DirectStreamTransform::StreamModes, readMode, br::DirectStreamTransform::Auto)
1031 1030  
1032 1031 bool timeVarying() const { return true; }
1033 1032  
... ... @@ -1068,6 +1067,7 @@ public:
1068 1067 basis.setParent(this->parent());
1069 1068 basis.transforms.clear();
1070 1069 basis.activeFrames = this->activeFrames;
  1070 + basis.readMode = this->readMode;
1071 1071  
1072 1072 // We need at least a CompositeTransform * to acess transform's children.
1073 1073 CompositeTransform * downcast = dynamic_cast<CompositeTransform *> (transform);
... ... @@ -1468,6 +1468,7 @@ void DirectStreamTransform::init()
1468 1468  
1469 1469 // Are our children time varying or not? This decides whether
1470 1470 // we run them in single threaded or multi threaded stages
  1471 + stage_variance.clear();
1471 1472 stage_variance.reserve(transforms.size());
1472 1473 foreach (const br::Transform *transform, transforms) {
1473 1474 stage_variance.append(transform->timeVarying());
... ...