Commit debbaa815e95949046d09fe3cfd96f35a05e1f86

Authored by Josh Klontz
2 parents befd0a8c 93632866

Merge branch 'master' into janus

README.md
@@ -11,3 +11,7 @@ To optionally check out a particular [tagged release](https://github.com/biometr @@ -11,3 +11,7 @@ To optionally check out a particular [tagged release](https://github.com/biometr
11 $ git submodule update 11 $ git submodule update
12 12
13 **[Build Instructions](http://openbiometrics.org/doxygen/latest/installation.html)** 13 **[Build Instructions](http://openbiometrics.org/doxygen/latest/installation.html)**
  14 +
  15 +
  16 +[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/biometrics/openbr/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
  17 +
openbr/openbr.cpp
@@ -323,6 +323,18 @@ unsigned char *br_unload_img(br_template tmpl) @@ -323,6 +323,18 @@ unsigned char *br_unload_img(br_template tmpl)
323 return t->m().data; 323 return t->m().data;
324 } 324 }
325 325
  326 +void br_free_template(br_template tmpl)
  327 +{
  328 + Template *t = reinterpret_cast<Template*>(tmpl);
  329 + delete t;
  330 +}
  331 +
  332 +void br_free_template_list(br_template_list tl)
  333 +{
  334 + TemplateList *realTL = reinterpret_cast<TemplateList*>(tl);
  335 + delete realTL;
  336 +}
  337 +
326 int br_img_rows(br_template tmpl) 338 int br_img_rows(br_template tmpl)
327 { 339 {
328 Template *t = reinterpret_cast<Template*>(tmpl); 340 Template *t = reinterpret_cast<Template*>(tmpl);
openbr/openbr.h
@@ -452,6 +452,14 @@ BR_EXPORT br_template br_load_img(const char *data, int len); @@ -452,6 +452,14 @@ BR_EXPORT br_template br_load_img(const char *data, int len);
452 */ 452 */
453 BR_EXPORT unsigned char* br_unload_img(br_template tmpl); 453 BR_EXPORT unsigned char* br_unload_img(br_template tmpl);
454 /*! 454 /*!
  455 + * \brief Free a br::Template's memory.
  456 + */
  457 +BR_EXPORT void br_free_template(br_template tmpl);
  458 +/*!
  459 + * \brief Free a br::TemplateList's memory.
  460 + */
  461 +BR_EXPORT void br_free_template_list(br_template_list tl);
  462 +/*!
455 * \brief Get the number of rows in an image. 463 * \brief Get the number of rows in an image.
456 * \param tmpl Pointer to a br::Template. 464 * \param tmpl Pointer to a br::Template.
457 */ 465 */
openbr/plugins/slidingwindow.cpp
@@ -38,7 +38,7 @@ static float getAspectRatio(const TemplateList &amp;data) @@ -38,7 +38,7 @@ static float getAspectRatio(const TemplateList &amp;data)
38 * Discards negative detections. 38 * Discards negative detections.
39 * \author Austin Blanton \cite imaus10 39 * \author Austin Blanton \cite imaus10
40 */ 40 */
41 -class SlidingWindowTransform : public MetaTransform 41 +class SlidingWindowTransform : public Transform
42 { 42 {
43 Q_OBJECT 43 Q_OBJECT
44 Q_PROPERTY(br::Transform *transform READ get_transform WRITE set_transform RESET reset_transform STORED false) 44 Q_PROPERTY(br::Transform *transform READ get_transform WRITE set_transform RESET reset_transform STORED false)
@@ -46,7 +46,7 @@ class SlidingWindowTransform : public MetaTransform @@ -46,7 +46,7 @@ class SlidingWindowTransform : public MetaTransform
46 Q_PROPERTY(bool takeFirst READ get_takeFirst WRITE set_takeFirst RESET reset_takeFirst STORED false) 46 Q_PROPERTY(bool takeFirst READ get_takeFirst WRITE set_takeFirst RESET reset_takeFirst STORED false)
47 Q_PROPERTY(float threshold READ get_threshold WRITE set_threshold RESET reset_threshold STORED false) 47 Q_PROPERTY(float threshold READ get_threshold WRITE set_threshold RESET reset_threshold STORED false)
48 Q_PROPERTY(float stepFraction READ get_stepFraction WRITE set_stepFraction RESET reset_stepFraction STORED false) 48 Q_PROPERTY(float stepFraction READ get_stepFraction WRITE set_stepFraction RESET reset_stepFraction STORED false)
49 - Q_PROPERTY(int ignoreBorder READ get_ignoreBorder WRITE set_ignoreBorder RESET reset_ignoreBorder STORED false) 49 + Q_PROPERTY(int ignoreBorder READ get_ignoreBorder WRITE set_ignoreBorder RESET reset_ignoreBorder STORED true)
50 BR_PROPERTY(br::Transform *, transform, NULL) 50 BR_PROPERTY(br::Transform *, transform, NULL)
51 BR_PROPERTY(int, windowWidth, 24) 51 BR_PROPERTY(int, windowWidth, 24)
52 BR_PROPERTY(bool, takeFirst, false) 52 BR_PROPERTY(bool, takeFirst, false)
@@ -56,9 +56,11 @@ class SlidingWindowTransform : public MetaTransform @@ -56,9 +56,11 @@ class SlidingWindowTransform : public MetaTransform
56 56
57 private: 57 private:
58 int windowHeight; 58 int windowHeight;
  59 + bool skipProject;
59 60
60 void train(const TemplateList &data) 61 void train(const TemplateList &data)
61 { 62 {
  63 + skipProject = true;
62 float aspectRatio = data.first().file.get<float>("aspectRatio", -1); 64 float aspectRatio = data.first().file.get<float>("aspectRatio", -1);
63 if (aspectRatio == -1) 65 if (aspectRatio == -1)
64 aspectRatio = getAspectRatio(data); 66 aspectRatio = getAspectRatio(data);
@@ -91,44 +93,40 @@ private: @@ -91,44 +93,40 @@ private:
91 93
92 void project(const Template &src, Template &dst) const 94 void project(const Template &src, Template &dst) const
93 { 95 {
94 - (void)src;(void)dst;qFatal("don't do that");  
95 - }  
96 -  
97 - void project(const TemplateList &src, TemplateList &dst) const  
98 - {  
99 - float scale = src.first().file.get<float>("scale", 1); 96 + float scale = src.file.get<float>("scale", 1);
100 projectHelp(src, dst, windowWidth, windowHeight, scale); 97 projectHelp(src, dst, windowWidth, windowHeight, scale);
101 } 98 }
102 99
103 -protected:  
104 - void projectHelp(const TemplateList &src, TemplateList &dst, int windowWidth, int windowHeight, float scale = 1) const  
105 - {  
106 - // no need to slide a window over ground truth data  
107 - if (src.first().file.getBool("Train", false)) { 100 + protected:
  101 + void projectHelp(const Template &src, Template &dst, int windowWidth, int windowHeight, float scale = 1) const
  102 + {
  103 +
  104 + dst = src;
  105 + if (skipProject) {
108 dst = src; 106 dst = src;
109 return; 107 return;
110 } 108 }
111 109
112 - foreach (const Template &t, src) {  
113 - for (float y = 0; y + windowHeight < t.m().rows; y += windowHeight*stepFraction) {  
114 - for (float x = 0; x + windowWidth < t.m().cols; x += windowWidth*stepFraction) {  
115 - Mat windowMat(t.m(), Rect(x + ignoreBorder, y + ignoreBorder, windowWidth - ignoreBorder * 2, windowHeight - ignoreBorder * 2));  
116 - Template detect;  
117 - transform->project(Template(t.file, windowMat), detect);  
118 -  
119 - // the result will be the only value in the Mat  
120 - float conf = detect.m().at<float>(0);  
121 - if (conf > threshold) {  
122 - detect.file.set("Detection", QRectF(x*scale, y*scale, windowWidth*scale, windowHeight*scale));  
123 - detect.file.set("Confidence", conf);  
124 - detect.file.clearRects();  
125 - dst.append(detect);  
126 - if (takeFirst)  
127 - return;  
128 - } 110 + Template windowTemplate(src.file, src);
  111 + QList<float> confidences = dst.file.getList<float>("Confidences", QList<float>());
  112 + for (float y = 0; y + windowHeight < src.m().rows; y += windowHeight*stepFraction) {
  113 + for (float x = 0; x + windowWidth < src.m().cols; x += windowWidth*stepFraction) {
  114 + Mat windowMat(src, Rect(x + ignoreBorder, y + ignoreBorder, windowWidth - ignoreBorder * 2, windowHeight - ignoreBorder * 2));
  115 + windowTemplate.replace(0,windowMat);
  116 + Template detect;
  117 + transform->project(windowTemplate, detect);
  118 + float conf = detect.m().at<float>(0);
  119 +
  120 + // the result will be in the Label
  121 + if (conf > threshold) {
  122 + dst.file.appendRect(QRectF(x*scale, y*scale, windowWidth*scale, windowHeight*scale));
  123 + confidences.append(conf);
  124 + if (takeFirst)
  125 + return;
129 } 126 }
130 } 127 }
131 } 128 }
  129 + dst.file.setList<float>("Confidences", confidences);
132 } 130 }
133 }; 131 };
134 132
@@ -144,7 +142,8 @@ class IntegralSlidingWindowTransform : public SlidingWindowTransform @@ -144,7 +142,8 @@ class IntegralSlidingWindowTransform : public SlidingWindowTransform
144 { 142 {
145 Q_OBJECT 143 Q_OBJECT
146 144
147 - void project(const TemplateList &src, TemplateList &dst) const 145 + private:
  146 + void project(const Template &src, Template &dst) const
148 { 147 {
149 // TODO: call SlidingWindowTransform::project on multiple scales 148 // TODO: call SlidingWindowTransform::project on multiple scales
150 SlidingWindowTransform::projectHelp(src, dst, 24, 24); 149 SlidingWindowTransform::projectHelp(src, dst, 24, 24);
@@ -217,10 +216,10 @@ static TemplateList cropTrainingSamples(const TemplateList &amp;data, const float as @@ -217,10 +216,10 @@ static TemplateList cropTrainingSamples(const TemplateList &amp;data, const float as
217 216
218 /*! 217 /*!
219 * \ingroup transforms 218 * \ingroup transforms
220 - * \brief Pass along images at different scales. 219 + * \brief .
221 * \author Austin Blanton \cite imaus10 220 * \author Austin Blanton \cite imaus10
222 */ 221 */
223 -class BuildScalesTransform : public MetaTransform 222 +class BuildScalesTransform : public Transform
224 { 223 {
225 Q_OBJECT 224 Q_OBJECT
226 Q_PROPERTY(br::Transform *transform READ get_transform WRITE set_transform RESET reset_transform STORED false) 225 Q_PROPERTY(br::Transform *transform READ get_transform WRITE set_transform RESET reset_transform STORED false)
@@ -243,9 +242,11 @@ class BuildScalesTransform : public MetaTransform @@ -243,9 +242,11 @@ class BuildScalesTransform : public MetaTransform
243 private: 242 private:
244 float aspectRatio; 243 float aspectRatio;
245 int windowHeight; 244 int windowHeight;
  245 + bool skipProject;
246 246
247 void train(const TemplateList &data) 247 void train(const TemplateList &data)
248 { 248 {
  249 + skipProject = true;
249 aspectRatio = getAspectRatio(data); 250 aspectRatio = getAspectRatio(data);
250 windowHeight = qRound(windowWidth / aspectRatio); 251 windowHeight = qRound(windowWidth / aspectRatio);
251 if (transform->trainable) { 252 if (transform->trainable) {
@@ -262,38 +263,29 @@ private: @@ -262,38 +263,29 @@ private:
262 263
263 void project(const Template &src, Template &dst) const 264 void project(const Template &src, Template &dst) const
264 { 265 {
265 - (void)src;(void)dst;qFatal("please don't");  
266 - }  
267 -  
268 - void project(const TemplateList &src, TemplateList &dst) const  
269 - {  
270 - // do not scale images during training  
271 - if (src.first().file.getBool("Train", false)) { 266 + dst = src;
  267 + if (skipProject) {
272 dst = src; 268 dst = src;
273 return; 269 return;
274 } 270 }
275 271
276 - foreach(const Template &t, src) {  
277 - int rows = t.m().rows;  
278 - int cols = t.m().cols;  
279 - int windowHeight = (int) qRound((float) windowWidth / aspectRatio);  
280 - float startScale;  
281 - if ((cols / rows) > aspectRatio)  
282 - startScale = qRound((float) rows / (float) windowHeight);  
283 - else  
284 - startScale = qRound((float) cols / (float) windowWidth);  
285 - for (float scale = startScale; scale >= minScale; scale -= (1.0 - scaleFactor)) {  
286 - Template scaleImg(t.file, Mat());  
287 - scaleImg.file.set("scale", scale);  
288 - resize(t.m(), scaleImg.m(), Size(qRound(cols / scale), qRound(rows / scale)));  
289 - TemplateList results;  
290 - TemplateList input;  
291 - input.append(scaleImg);  
292 - transform->project(input, results);  
293 - dst.append(results);  
294 - if (takeLargestScale && !dst.empty())  
295 - return;  
296 - } 272 + int rows = src.m().rows;
  273 + int cols = src.m().cols;
  274 + int windowHeight = (int) qRound((float) windowWidth / aspectRatio);
  275 +
  276 + float startScale;
  277 + if ((cols / rows) > aspectRatio)
  278 + startScale = qRound((float) rows / (float) windowHeight);
  279 + else
  280 + startScale = qRound((float) cols / (float) windowWidth);
  281 +
  282 + for (float scale = startScale; scale >= minScale; scale -= (1.0 - scaleFactor)) {
  283 + Template scaleImg(dst.file, Mat());
  284 + scaleImg.file.set("scale", scale);
  285 + resize(src, scaleImg, Size(qRound(cols / scale), qRound(rows / scale)));
  286 + transform->project(scaleImg, dst);
  287 + if (takeLargestScale && !dst.file.rects().empty())
  288 + return;
297 } 289 }
298 } 290 }
299 291
@@ -384,21 +376,12 @@ private: @@ -384,21 +376,12 @@ private:
384 376
385 void project(const Template &src, Template &dst) const 377 void project(const Template &src, Template &dst) const
386 { 378 {
387 - (void)src;(void)dst;qFatal("nope");  
388 - }  
389 -  
390 - void project(const TemplateList &src, TemplateList &dst) const  
391 - {  
392 - QList<Rect> rects;  
393 - QList<float> confidences;  
394 - foreach (const Template &t, src) {  
395 - if (t.file.contains("Detection")) {  
396 - rects.append(OpenCVUtils::toRect(t.file.get<QRectF>("Detection")));  
397 - confidences.append(t.file.get<float>("Confidence"));  
398 - }  
399 - } 379 + dst = src;
  380 + if (!dst.file.contains("Confidences"))
  381 + return;
400 382
401 - // Compute overlap between rectangles and create discrete Laplacian matrix 383 + //Compute overlap between rectangles and create discrete Laplacian matrix
  384 + QList<Rect> rects = OpenCVUtils::toRects(src.file.rects());
402 int n = rects.size(); 385 int n = rects.size();
403 if (n == 0) 386 if (n == 0)
404 return; 387 return;
@@ -462,6 +445,7 @@ private: @@ -462,6 +445,7 @@ private:
462 cnts[i] = 0; 445 cnts[i] = 0;
463 } 446 }
464 447
  448 + QList<float> confidences = dst.file.getList<float>("Confidences");
465 for (int i = 0; i < n; i++) { 449 for (int i = 0; i < n; i++) {
466 mx = 0.0; 450 mx = 0.0;
467 mxIdx = -1; 451 mxIdx = -1;
@@ -496,13 +480,6 @@ private: @@ -496,13 +480,6 @@ private:
496 } 480 }
497 } 481 }
498 482
499 - for (int i=0; i<consolidatedRects.size(); i++) {  
500 - Template t(src.first().file);  
501 - t.file.set("Detection", OpenCVUtils::fromRect(consolidatedRects.at(i)));  
502 - t.file.set("Confidence", consolidatedConfidences.at(i));  
503 - dst.append(t);  
504 - }  
505 -  
506 delete [] midX; 483 delete [] midX;
507 delete [] midY; 484 delete [] midY;
508 delete [] avgWidth; 485 delete [] avgWidth;
@@ -510,11 +487,43 @@ private: @@ -510,11 +487,43 @@ private:
510 delete [] confs; 487 delete [] confs;
511 delete [] cnts; 488 delete [] cnts;
512 489
  490 + dst.file.setRects(consolidatedRects);
  491 + dst.file.setList<float>("Confidences", consolidatedConfidences);
513 } 492 }
514 }; 493 };
515 494
516 BR_REGISTER(Transform, ConsolidateDetectionsTransform) 495 BR_REGISTER(Transform, ConsolidateDetectionsTransform)
517 496
  497 +/*!
  498 + * \ingroup transforms
  499 + * \brief For each rectangle bounding box in src, a new
  500 + * template is created.
  501 + * \author Brendan Klare \cite bklare
  502 + */
  503 +class RectsToTemplatesTransform : public UntrainableMetaTransform
  504 +{
  505 + Q_OBJECT
  506 +
  507 +private:
  508 + void project(const Template &src, Template &dst) const
  509 + {
  510 + Template tOut(src.file);
  511 + QList<float> confidences = src.file.getList<float>("Confidences");
  512 + QList<QRectF> rects = src.file.rects();
  513 + for (int i = 0; i < rects.size(); i++) {
  514 + Mat m(src, OpenCVUtils::toRect(rects[i]));
  515 + Template t(src.file, m);
  516 + t.file.set("Confidence", confidences[i]);
  517 + t.file.clearRects();
  518 + tOut << t;
  519 + }
  520 + dst = tOut;
  521 + }
  522 +};
  523 +
  524 +BR_REGISTER(Transform, RectsToTemplatesTransform)
  525 +
  526 +
518 } // namespace br 527 } // namespace br
519 528
520 #include "slidingwindow.moc" 529 #include "slidingwindow.moc"