Commit 570e3750cb8fdb927f36c825ef8825e3da19f51f

Authored by Brendan Klare
2 parents b101367f aff1aa31

Merge branch 'master' of https://github.com/biometrics/openbr

openbr/plugins/algorithms.cpp
@@ -46,12 +46,13 @@ class AlgorithmsInitializer : public Initializer @@ -46,12 +46,13 @@ class AlgorithmsInitializer : public Initializer
46 Globals->abbreviations.insert("CropFace", "Open+Cvt(Gray)+Cascade(FrontalFace)+ASEFEyes+Affine(128,128,0.25,0.35)"); 46 Globals->abbreviations.insert("CropFace", "Open+Cvt(Gray)+Cascade(FrontalFace)+ASEFEyes+Affine(128,128,0.25,0.35)");
47 47
48 // Video 48 // Video
49 - Globals->abbreviations.insert("DisplayVideo", "Stream([FPSLimit(30)+Show(false,[FrameNumber])+Discard])");  
50 - Globals->abbreviations.insert("PerFrameDetection", "Stream([SaveMat(original)+Cvt(Gray)+Cascade(FrontalFace)+ASEFEyes+RestoreMat(original)+Draw(inPlace=true),Show(false,[FrameNumber])+Discard])");  
51 - Globals->abbreviations.insert("AgeGenderDemo", "Stream([SaveMat(original)+Cvt(Gray)+Cascade(FrontalFace)+Expand+<FaceClassificationRegistration>+<FaceClassificationExtraction>+<AgeRegressor>/<GenderClassifier>+Discard+RestoreMat(original)+Draw(inPlace=true)+DrawPropertiesPoint([Age,Gender],Affine_0,inPlace=true)+SaveMat(original)+Discard+Contract,RestoreMat(original)+FPSCalc+Show(false,[AvgFPS,Age,Gender])+Discard])");  
52 - Globals->abbreviations.insert("HOG", "Stream([DropFrames(5)+Cvt(Gray)+KeyPointDetector(SIFT)+ROI+Expand+Resize(32,32)+Gradient+RectRegions+Bin(0,360,8)+Hist(8)+Cat])+Contract+CatRows+KMeans(500)+Hist(500)+SVM");  
53 - Globals->abbreviations.insert("HOF", "Stream([DropFrames(5)+KeyPointDetector(SIFT),AggregateFrames(2),OpticalFlow+ROI+Expand+Resize(32,32)+Gradient+RectRegions+Bin(0,360,8)+Hist(8)+Cat])+Contract+CatRows+KMeans(500)+Hist(500)");  
54 - Globals->abbreviations.insert("HOGHOF", "Stream([DropFrames(5)+Cvt(Gray),KeyPointDetector(SIFT),AggregateFrames(2),(OpticalFlow+Gradient+Bin(0,360,8)+ROI+Hist(8))/(First+Gradient+Bin(0,360,8)+ROI+Hist(8)),CatCols])+Contract+CatRows+KMeans(500)+Hist(500)"); 49 + Globals->abbreviations.insert("DisplayVideo", "Stream(FPSLimit(30)+Show(false,[FrameNumber])+Discard)");
  50 + Globals->abbreviations.insert("PerFrameDetection", "Stream(SaveMat(original)+Cvt(Gray)+Cascade(FrontalFace)+ASEFEyes+RestoreMat(original)+Draw(inPlace=true)+Show(false,[FrameNumber])+Discard)");
  51 + Globals->abbreviations.insert("AgeGenderDemo", "Stream(SaveMat(original)+Cvt(Gray)+Cascade(FrontalFace)+Expand+<FaceClassificationRegistration>+<FaceClassificationExtraction>+<AgeRegressor>/<GenderClassifier>+Discard+RestoreMat(original)+Draw(inPlace=true)+DrawPropertiesPoint([Age,Gender],Affine_0,inPlace=true)+SaveMat(original)+Discard+Contract+RestoreMat(original)+FPSCalc+Show(false,[AvgFPS,Age,Gender])+Discard)");
  52 +
  53 + Globals->abbreviations.insert("HOG", "Stream(DropFrames(5)+Cvt(Gray)+KeyPointDetector(SIFT)+ROI+Expand+Resize(32,32)+Gradient+RectRegions+Bin(0,360,8)+Hist(8)+Cat)+Contract+CatRows+KMeans(500)+Hist(500)+SVM");
  54 + Globals->abbreviations.insert("HOF", "Stream(DropFrames(5)+KeyPointDetector(SIFT)+AggregateFrames(2)+OpticalFlow+ROI+Expand+Resize(32,32)+Gradient+RectRegions+Bin(0,360,8)+Hist(8)+Cat)+Contract+CatRows+KMeans(500)+Hist(500)");
  55 + Globals->abbreviations.insert("HOGHOF", "Stream(DropFrames(5)+Cvt(Gray),KeyPointDetector(SIFT)+AggregateFrames(2)+(OpticalFlow+Gradient+Bin(0,360,8)+ROI+Hist(8))/(First+Gradient+Bin(0,360,8)+ROI+Hist(8))+CatCols)+Contract+CatRows+KMeans(500)+Hist(500)");
55 56
56 // Generic Image Processing 57 // Generic Image Processing
57 Globals->abbreviations.insert("SIFT", "Open+KeyPointDetector(SIFT)+KeyPointDescriptor(SIFT):KeyPointMatcher(BruteForce)"); 58 Globals->abbreviations.insert("SIFT", "Open+KeyPointDetector(SIFT)+KeyPointDescriptor(SIFT):KeyPointMatcher(BruteForce)");
openbr/plugins/meta.cpp
@@ -614,6 +614,11 @@ public: @@ -614,6 +614,11 @@ public:
614 614
615 void train(const TemplateList &data) 615 void train(const TemplateList &data)
616 { 616 {
  617 + if (!transform->trainable) {
  618 + qWarning("Attempted to train untrainable transform, nothing will happen.");
  619 + return;
  620 + }
  621 +
617 transform->train(data); 622 transform->train(data);
618 } 623 }
619 624
@@ -628,7 +633,6 @@ public: @@ -628,7 +633,6 @@ public:
628 else dst = output[0]; 633 else dst = output[0];
629 } 634 }
630 635
631 -  
632 // For each input template, form a single element TemplateList, push all those 636 // For each input template, form a single element TemplateList, push all those
633 // lists through transform, and form dst by concatenating the results. 637 // lists through transform, and form dst by concatenating the results.
634 // Process the single elemnt templates in parallel if parallelism is enabled. 638 // Process the single elemnt templates in parallel if parallelism is enabled.
@@ -677,7 +681,6 @@ public: @@ -677,7 +681,6 @@ public:
677 681
678 void init() 682 void init()
679 { 683 {
680 -  
681 if (transform && transform->timeVarying()) 684 if (transform && transform->timeVarying())
682 transform = new br::TimeInvariantWrapperTransform(transform); 685 transform = new br::TimeInvariantWrapperTransform(transform);
683 } 686 }
openbr/plugins/openbr_internal.h
@@ -122,7 +122,10 @@ public: @@ -122,7 +122,10 @@ public:
122 122
123 TimeInvariantWrapperTransform(Transform * basis) : transformSource(new TransformCopier(basis)) 123 TimeInvariantWrapperTransform(Transform * basis) : transformSource(new TransformCopier(basis))
124 { 124 {
  125 + if (!basis)
  126 + qFatal("TimeInvariantWrapper created with NULL transform");
125 baseTransform = basis; 127 baseTransform = basis;
  128 + trainable = basis->trainable;
126 } 129 }
127 130
128 virtual void project(const Template &src, Template &dst) const 131 virtual void project(const Template &src, Template &dst) const
@@ -132,7 +135,6 @@ public: @@ -132,7 +135,6 @@ public:
132 transformSource.release(aTransform); 135 transformSource.release(aTransform);
133 } 136 }
134 137
135 -  
136 void project(const TemplateList &src, TemplateList &dst) const 138 void project(const TemplateList &src, TemplateList &dst) const
137 { 139 {
138 Transform * aTransform = transformSource.acquire(); 140 Transform * aTransform = transformSource.acquire();
openbr/plugins/stream.cpp
@@ -649,7 +649,7 @@ public: @@ -649,7 +649,7 @@ public:
649 class ProcessingStage 649 class ProcessingStage
650 { 650 {
651 public: 651 public:
652 - friend class StreamTransform; 652 + friend class DirectStreamTransform;
653 public: 653 public:
654 ProcessingStage(int nThreads = 1) 654 ProcessingStage(int nThreads = 1)
655 { 655 {
@@ -1015,17 +1015,20 @@ public: @@ -1015,17 +1015,20 @@ public:
1015 }; 1015 };
1016 1016
1017 1017
1018 -class StreamTransform : public CompositeTransform 1018 +
  1019 +class DirectStreamTransform : public CompositeTransform
1019 { 1020 {
1020 Q_OBJECT 1021 Q_OBJECT
1021 public: 1022 public:
1022 Q_PROPERTY(int activeFrames READ get_activeFrames WRITE set_activeFrames RESET reset_activeFrames) 1023 Q_PROPERTY(int activeFrames READ get_activeFrames WRITE set_activeFrames RESET reset_activeFrames)
1023 BR_PROPERTY(int, activeFrames, 100) 1024 BR_PROPERTY(int, activeFrames, 100)
1024 1025
  1026 + friend class StreamTransfrom;
  1027 +
1025 void train(const TemplateList & data) 1028 void train(const TemplateList & data)
1026 { 1029 {
1027 if (!trainable) { 1030 if (!trainable) {
1028 - qWarning("How did this happen? You're training a nontrainable transform."); 1031 + qWarning("Attempted to train untrainable transform, nothing will happen.");
1029 return; 1032 return;
1030 } 1033 }
1031 qFatal("Stream train is currently not implemented."); 1034 qFatal("Stream train is currently not implemented.");
@@ -1115,6 +1118,10 @@ public: @@ -1115,6 +1118,10 @@ public:
1115 { 1118 {
1116 if (transforms.isEmpty()) return; 1119 if (transforms.isEmpty()) return;
1117 1120
  1121 + for (int i=0; i < processingStages.size();i++)
  1122 + delete processingStages[i];
  1123 + processingStages.clear();
  1124 +
1118 // call CompositeTransform::init so that trainable is set 1125 // call CompositeTransform::init so that trainable is set
1119 // correctly. 1126 // correctly.
1120 CompositeTransform::init(); 1127 CompositeTransform::init();
@@ -1190,12 +1197,13 @@ public: @@ -1190,12 +1197,13 @@ public:
1190 collectionStage->nextStage = readStage; 1197 collectionStage->nextStage = readStage;
1191 } 1198 }
1192 1199
1193 - ~StreamTransform() 1200 + ~DirectStreamTransform()
1194 { 1201 {
1195 // Delete all the stages 1202 // Delete all the stages
1196 for (int i = 0; i < processingStages.size(); i++) { 1203 for (int i = 0; i < processingStages.size(); i++) {
1197 delete processingStages[i]; 1204 delete processingStages[i];
1198 } 1205 }
  1206 + processingStages.clear();
1199 } 1207 }
1200 1208
1201 protected: 1209 protected:
@@ -1237,12 +1245,150 @@ protected: @@ -1237,12 +1245,150 @@ protected:
1237 } 1245 }
1238 }; 1246 };
1239 1247
1240 -QHash<QObject *, QThreadPool *> StreamTransform::pools;  
1241 -QMutex StreamTransform::poolsAccess; 1248 +QHash<QObject *, QThreadPool *> DirectStreamTransform::pools;
  1249 +QMutex DirectStreamTransform::poolsAccess;
  1250 +
  1251 +BR_REGISTER(Transform, DirectStreamTransform)
  1252 +
  1253 +;
  1254 +
  1255 +class StreamTransform : public TimeVaryingTransform
  1256 +{
  1257 + Q_OBJECT
  1258 +
  1259 +public:
  1260 + StreamTransform() : TimeVaryingTransform(false)
  1261 + {
  1262 + }
  1263 +
  1264 + Q_PROPERTY(br::Transform *transform READ get_transform WRITE set_transform STORED false)
  1265 + Q_PROPERTY(int activeFrames READ get_activeFrames WRITE set_activeFrames RESET reset_activeFrames)
  1266 + BR_PROPERTY(br::Transform *, transform, NULL)
  1267 + BR_PROPERTY(int, activeFrames, 100)
  1268 +
  1269 + bool timeVarying() const { return true; }
  1270 +
  1271 + void project(const Template &src, Template &dst) const
  1272 + {
  1273 + basis.project(src,dst);
  1274 + }
  1275 +
  1276 + void projectUpdate(const Template &src, Template &dst)
  1277 + {
  1278 + basis.projectUpdate(src,dst);
  1279 + }
  1280 + void projectUpdate(const TemplateList & src, TemplateList & dst)
  1281 + {
  1282 + basis.projectUpdate(src,dst);
  1283 + }
  1284 +
  1285 +
  1286 + void train(const TemplateList & data)
  1287 + {
  1288 + basis.train(data);
  1289 + }
  1290 +
  1291 + virtual void finalize(TemplateList & output)
  1292 + {
  1293 + (void) output;
  1294 + // Nothing in particular to do here, stream calls finalize
  1295 + // on all child transforms as part of projectUpdate
  1296 + }
  1297 +
  1298 + // reinterpret transform, set up the actual stream. We can only reinterpret pipes
  1299 + void init()
  1300 + {
  1301 + if (!transform)
  1302 + return;
  1303 + trainable = transform->trainable;
  1304 +
  1305 + basis.setParent(this->parent());
  1306 + basis.transforms.clear();
  1307 + basis.activeFrames = this->activeFrames;
  1308 +
  1309 + // We need at least a CompositeTransform * to acess transform's children.
  1310 + CompositeTransform * downcast = dynamic_cast<CompositeTransform *> (transform);
  1311 +
  1312 + // If this isn't even a composite transform, or it's not a pipe, just set up
  1313 + // basis with 1 stage.
  1314 + if (!downcast || QString(transform->metaObject()->className()) != "br::PipeTransform")
  1315 + {
  1316 + basis.transforms.append(transform);
  1317 + basis.init();
  1318 + return;
  1319 + }
  1320 + if (downcast->transforms.empty())
  1321 + {
  1322 + qWarning("Trying to set up empty stream");
  1323 + basis.init();
  1324 + return;
  1325 + }
  1326 +
  1327 + // OK now we will regroup downcast's children
  1328 + QList<QList<Transform *> > sets;
  1329 + sets.append(QList<Transform *> ());
  1330 + sets.last().append(downcast->transforms[0]);
  1331 + if (downcast->transforms[0]->timeVarying())
  1332 + sets.append(QList<Transform *> ());
  1333 +
  1334 + for (int i=1;i < downcast->transforms.size(); i++) {
  1335 + // If this is time varying it becomse its own stage
  1336 + if (downcast->transforms[i]->timeVarying()) {
  1337 + // If a set was already active, we add another one
  1338 + if (!sets.last().empty()) {
  1339 + sets.append(QList<Transform *>());
  1340 + }
  1341 + // add the item
  1342 + sets.last().append(downcast->transforms[i]);
  1343 + // Add another set to indicate separation.
  1344 + sets.append(QList<Transform *>());
  1345 + }
  1346 + // otherwise, we can combine non time-varying stages
  1347 + else {
  1348 + sets.last().append(downcast->transforms[i]);
  1349 + }
  1350 +
  1351 + }
  1352 + if (sets.last().empty())
  1353 + sets.removeLast();
  1354 +
  1355 + QList<Transform *> transform_set;
  1356 + transform_set.reserve(sets.size());
  1357 + for (int i=0; i < sets.size(); i++) {
  1358 + // If this is a single transform set, we add that to the list
  1359 + if (sets[i].size() == 1 ) {
  1360 + transform_set.append(sets[i].at(0));
  1361 + }
  1362 + //otherwise we build a pipe
  1363 + else {
  1364 + CompositeTransform * pipe = dynamic_cast<CompositeTransform *>(Transform::make("Pipe([])", this));
  1365 + pipe->transforms = sets[i];
  1366 + pipe->init();
  1367 + transform_set.append(pipe);
  1368 + }
  1369 + }
  1370 +
  1371 + basis.transforms = transform_set;
  1372 + basis.init();
  1373 + }
  1374 +
  1375 + Transform * smartCopy()
  1376 + {
  1377 + // We just want the DirectStream to begin with, so just return a copy of that.
  1378 + DirectStreamTransform * res = (DirectStreamTransform *) basis.smartCopy();
  1379 + res->activeFrames = this->activeFrames;
  1380 + return res;
  1381 + }
  1382 +
  1383 +
  1384 +private:
  1385 + DirectStreamTransform basis;
  1386 +};
1242 1387
1243 BR_REGISTER(Transform, StreamTransform) 1388 BR_REGISTER(Transform, StreamTransform)
1244 1389
1245 1390
  1391 +
1246 } // namespace br 1392 } // namespace br
1247 1393
1248 #include "stream.moc" 1394 #include "stream.moc"
1 -Subproject commit c11ff0f0bb451fb5576bd4b8122c32278e52042a 1 +Subproject commit a73d51013ea05f263e88a28539393159fff2183e