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 11 $ git submodule update
12 12  
13 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 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 338 int br_img_rows(br_template tmpl)
327 339 {
328 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 452 */
453 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 463 * \brief Get the number of rows in an image.
456 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 38 * Discards negative detections.
39 39 * \author Austin Blanton \cite imaus10
40 40 */
41   -class SlidingWindowTransform : public MetaTransform
  41 +class SlidingWindowTransform : public Transform
42 42 {
43 43 Q_OBJECT
44 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 46 Q_PROPERTY(bool takeFirst READ get_takeFirst WRITE set_takeFirst RESET reset_takeFirst STORED false)
47 47 Q_PROPERTY(float threshold READ get_threshold WRITE set_threshold RESET reset_threshold STORED false)
48 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 50 BR_PROPERTY(br::Transform *, transform, NULL)
51 51 BR_PROPERTY(int, windowWidth, 24)
52 52 BR_PROPERTY(bool, takeFirst, false)
... ... @@ -56,9 +56,11 @@ class SlidingWindowTransform : public MetaTransform
56 56  
57 57 private:
58 58 int windowHeight;
  59 + bool skipProject;
59 60  
60 61 void train(const TemplateList &data)
61 62 {
  63 + skipProject = true;
62 64 float aspectRatio = data.first().file.get<float>("aspectRatio", -1);
63 65 if (aspectRatio == -1)
64 66 aspectRatio = getAspectRatio(data);
... ... @@ -91,44 +93,40 @@ private:
91 93  
92 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 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 106 dst = src;
109 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 142 {
145 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 148 // TODO: call SlidingWindowTransform::project on multiple scales
150 149 SlidingWindowTransform::projectHelp(src, dst, 24, 24);
... ... @@ -217,10 +216,10 @@ static TemplateList cropTrainingSamples(const TemplateList &amp;data, const float as
217 216  
218 217 /*!
219 218 * \ingroup transforms
220   - * \brief Pass along images at different scales.
  219 + * \brief .
221 220 * \author Austin Blanton \cite imaus10
222 221 */
223   -class BuildScalesTransform : public MetaTransform
  222 +class BuildScalesTransform : public Transform
224 223 {
225 224 Q_OBJECT
226 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 242 private:
244 243 float aspectRatio;
245 244 int windowHeight;
  245 + bool skipProject;
246 246  
247 247 void train(const TemplateList &data)
248 248 {
  249 + skipProject = true;
249 250 aspectRatio = getAspectRatio(data);
250 251 windowHeight = qRound(windowWidth / aspectRatio);
251 252 if (transform->trainable) {
... ... @@ -262,38 +263,29 @@ private:
262 263  
263 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 268 dst = src;
273 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 376  
385 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 385 int n = rects.size();
403 386 if (n == 0)
404 387 return;
... ... @@ -462,6 +445,7 @@ private:
462 445 cnts[i] = 0;
463 446 }
464 447  
  448 + QList<float> confidences = dst.file.getList<float>("Confidences");
465 449 for (int i = 0; i < n; i++) {
466 450 mx = 0.0;
467 451 mxIdx = -1;
... ... @@ -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 483 delete [] midX;
507 484 delete [] midY;
508 485 delete [] avgWidth;
... ... @@ -510,11 +487,43 @@ private:
510 487 delete [] confs;
511 488 delete [] cnts;
512 489  
  490 + dst.file.setRects(consolidatedRects);
  491 + dst.file.setList<float>("Confidences", consolidatedConfidences);
513 492 }
514 493 };
515 494  
516 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 527 } // namespace br
519 528  
520 529 #include "slidingwindow.moc"
... ...