Commit 69df11eb405aef9bb0587f1ce6e2bd46843c2088

Authored by sklum
2 parents 9cf029b5 2cc56616

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

Conflicts:
	openbr/core/core.cpp
openbr/core/core.cpp
... ... @@ -139,7 +139,6 @@ struct AlgorithmCore
139 139 downcast->transforms[0] = this->transform.data();
140 140 downcast->init();
141 141  
142   -
143 142 downcast->projectUpdate(i,i);
144 143  
145 144 return i.files();
... ...
openbr/core/qtutils.cpp
... ... @@ -399,33 +399,31 @@ void showFile(const QString &file)
399 399  
400 400 QString toString(const QVariant &variant)
401 401 {
402   - if (variant.canConvert(QVariant::String))
403   - return variant.toString();
404   - else if(variant.canConvert(QVariant::PointF)) {
405   - QPointF pt = qvariant_cast<QPointF>(variant);
406   - return QString("(%1,%2)").arg(QString::number(pt.x()),
407   - QString::number(pt.y()));
408   - }
409   - else if (variant.canConvert(QVariant::RectF)) {
  402 + if (variant.canConvert(QVariant::List)) return toString(qvariant_cast<QVariantList>(variant));
  403 + else if (variant.canConvert(QVariant::String)) return variant.toString();
  404 + else if (variant.canConvert(QVariant::PointF)) {
  405 + QPointF point = qvariant_cast<QPointF>(variant);
  406 + return QString("(%1,%2)").arg(QString::number(point.x()),QString::number(point.y()));
  407 + } else if (variant.canConvert(QVariant::RectF)) {
410 408 QRectF rect = qvariant_cast<QRectF>(variant);
411 409 return QString("(%1,%2,%3,%4)").arg(QString::number(rect.x()),
412 410 QString::number(rect.y()),
413 411 QString::number(rect.width()),
414 412 QString::number(rect.height()));
415 413 }
416   - else if (variant.canConvert(QVariant::List)) {
417   - QString ret = QString("[");
418   - bool first = true;
419   - foreach (const QVariant &i, variant.toList()) {
420   - if (!first)
421   - ret += ",";
422   - else
423   - first = false;
424   - ret += toString(i);
425   - }
426   - ret += "]";
427   - return ret;
428   - }
  414 +
  415 + return QString();
  416 +}
  417 +
  418 +QString toString(const QVariantList &variantList)
  419 +{
  420 + QStringList variants;
  421 +
  422 + foreach(const QVariant &variant, variantList)
  423 + variants.append(toString(variant));
  424 +
  425 + if (!variants.isEmpty()) return "[" + variants.join(", ") + "]";
  426 +
429 427 return QString();
430 428 }
431 429  
... ...
openbr/core/qtutils.h
... ... @@ -74,6 +74,7 @@ namespace QtUtils
74 74  
75 75 /**** Variant Utilities ****/
76 76 QString toString(const QVariant &variant);
  77 + QString toString(const QVariantList &variantList);
77 78  
78 79 template <typename T>
79 80 QVariantList toVariantList(const QList<T> &list)
... ...
openbr/openbr_plugin.cpp
... ... @@ -58,16 +58,7 @@ QString File::flat() const
58 58 foreach (const QString &key, keys) {
59 59 const QVariant value = this->value(key);
60 60 if (value.isNull()) values.append(key);
61   - else {
62   - if (QString(value.typeName()) == "QVariantList") {
63   - QStringList variants;
64   - foreach(const QVariant &variant, qvariant_cast<QVariantList>(value)) {
65   - variants.append(QtUtils::toString(variant));
66   - }
67   - if (!variants.isEmpty()) values.append(key + "=[" + variants.join(", ") + "]");
68   - }
69   - else values.append(key + "=" + QtUtils::toString(value));
70   - }
  61 + else values.append(key + "=" + QtUtils::toString(value));
71 62 }
72 63  
73 64 QString flat = name;
... ...
openbr/plugins/regions.cpp
... ... @@ -345,9 +345,12 @@ class RectFromPointsTransform : public UntrainableTransform
345 345  
346 346 dst.file.setPoints(points);
347 347  
348   - if (crop) dst.m() = src.m()(Rect(std::max(0.0, minX - deltaWidth/2.0), std::max(0.0, minY - deltaHeight/2.0), std::min((double)src.m().cols, width), std::min((double)src.m().rows, height)));
  348 + const int x = std::max(0.0, minX - deltaWidth/2.0);
  349 + const int y = std::max(0.0, minY - deltaHeight/2.0);
  350 +
  351 + if (crop) dst.m() = src.m()(Rect(x, y, std::min((double)src.m().cols-x, width), std::min((double)src.m().rows-y, height)));
349 352 else {
350   - dst.file.appendRect(QRectF(std::max(0.0, minX - deltaWidth/2.0), std::max(0.0, minY - deltaHeight/2.0), std::min((double)src.m().cols, width), std::min((double)src.m().rows, height)));
  353 + dst.file.appendRect(QRectF(x, y, std::min((double)src.m().cols-x, width), std::min((double)src.m().rows-y, height)));
351 354 dst.m() = src.m();
352 355 }
353 356 }
... ...
openbr/plugins/slidingwindow.cpp
... ... @@ -8,12 +8,28 @@
8 8  
9 9 using namespace cv;
10 10  
11   -// Because MSVC doesn't provide a round() function in math.h
12   -static int round(float x) { return (floor(x + 0.5)); }
13   -
14 11 namespace br
15 12 {
16 13  
  14 +// Find avg aspect ratio
  15 +static float getAspectRatio(const TemplateList &data)
  16 +{
  17 + double tempRatio = 0;
  18 + int ratioCnt = 0;
  19 +
  20 + foreach (const Template &tmpl, data) {
  21 + QList<Rect> posRects = OpenCVUtils::toRects(tmpl.file.rects());
  22 + foreach (const Rect &posRect, posRects) {
  23 + if (posRect.x + posRect.width >= tmpl.m().cols || posRect.y + posRect.height >= tmpl.m().rows || posRect.x < 0 || posRect.y < 0) {
  24 + continue;
  25 + }
  26 + tempRatio += (float)posRect.width / (float)posRect.height;
  27 + ratioCnt += 1;
  28 + }
  29 + }
  30 + return tempRatio / (double)ratioCnt;
  31 +}
  32 +
17 33 /*!
18 34 * \ingroup transforms
19 35 * \brief Applies a transform to a sliding window.
... ... @@ -25,23 +41,19 @@ class SlidingWindowTransform : public Transform
25 41 Q_OBJECT
26 42 Q_PROPERTY(br::Transform *transform READ get_transform WRITE set_transform RESET reset_transform STORED false)
27 43 Q_PROPERTY(int minSize READ get_minSize WRITE set_minSize RESET reset_minSize STORED false)
28   - Q_PROPERTY(double scaleFactor READ get_scaleFactor WRITE set_scaleFactor RESET reset_scaleFactor STORED false)
29 44 Q_PROPERTY(int stepSize READ get_stepSize WRITE set_stepSize RESET reset_stepSize STORED false)
30   - Q_PROPERTY(bool takeLargestScale READ get_takeLargestScale WRITE set_takeLargestScale RESET reset_takeLargestScale STORED false)
  45 + Q_PROPERTY(bool takeFirst READ get_takeFirst WRITE set_takeFirst RESET reset_takeFirst STORED false)
31 46 Q_PROPERTY(bool negSamples READ get_negSamples WRITE set_negSamples RESET reset_negSamples STORED false)
32 47 Q_PROPERTY(int negToPosRatio READ get_negToPosRatio WRITE set_negToPosRatio RESET reset_negToPosRatio STORED false)
33 48 Q_PROPERTY(double maxOverlap READ get_maxOverlap WRITE set_maxOverlap RESET reset_maxOverlap STORED false)
34   - Q_PROPERTY(float aspectRatio READ get_aspectRatio WRITE set_aspectRatio RESET reset_aspectRatio STORED true)
35 49 Q_PROPERTY(int windowWidth READ get_windowWidth WRITE set_windowWidth RESET reset_windowWidth STORED false)
36 50 BR_PROPERTY(br::Transform *, transform, NULL)
37 51 BR_PROPERTY(int, minSize, 8)
38   - BR_PROPERTY(double, scaleFactor, 0.75)
39 52 BR_PROPERTY(int, stepSize, 1)
40   - BR_PROPERTY(bool, takeLargestScale, true)
  53 + BR_PROPERTY(bool, takeFirst, true)
41 54 BR_PROPERTY(bool, negSamples, true)
42 55 BR_PROPERTY(int, negToPosRatio, 1)
43 56 BR_PROPERTY(double, maxOverlap, 0)
44   - BR_PROPERTY(float, aspectRatio, 1)
45 57 BR_PROPERTY(int, windowWidth, 24)
46 58  
47 59 public:
... ... @@ -50,24 +62,14 @@ private:
50 62  
51 63 void train(const TemplateList &data)
52 64 {
  65 + // only calculate if the work hasn't been done
  66 + aspectRatio = data.first().file.get<float>("aspectRatio", -1);
  67 + if (aspectRatio == -1)
  68 + aspectRatio = getAspectRatio(data);
  69 +
53 70 if (transform->trainable) {
54   - double tempRatio = 0;
55   - int ratioCnt = 0;
56 71 TemplateList full;
57 72  
58   - //First find avg aspect ratio
59   - foreach (const Template &tmpl, data) {
60   - QList<Rect> posRects = OpenCVUtils::toRects(tmpl.file.rects());
61   - foreach (const Rect &posRect, posRects) {
62   - if (posRect.x + posRect.width >= tmpl.m().cols || posRect.y + posRect.height >= tmpl.m().rows || posRect.x < 0 || posRect.y < 0) {
63   - continue;
64   - }
65   - tempRatio += (float)posRect.width / (float)posRect.height;
66   - ratioCnt += 1;
67   - }
68   - }
69   - aspectRatio = tempRatio / (double)ratioCnt;
70   -
71 73 foreach (const Template &tmpl, data) {
72 74 QList<Rect> posRects = OpenCVUtils::toRects(tmpl.file.rects());
73 75 QList<Rect> negRects;
... ... @@ -83,7 +85,7 @@ private:
83 85 }
84 86  
85 87 Mat scaledImg;
86   - resize(Mat(tmpl, posRect), scaledImg, Size(windowWidth,round(windowWidth / aspectRatio)));
  88 + resize(Mat(tmpl, posRect), scaledImg, Size(windowWidth,qRound(windowWidth / aspectRatio)));
87 89 Template pos(tmpl.file, scaledImg);
88 90 full += pos;
89 91  
... ... @@ -132,43 +134,94 @@ private:
132 134 if (src.file.getBool("Train", false)) return;
133 135  
134 136 dst.file.clearRects();
  137 + int windowHeight = (int) qRound((float) windowWidth / aspectRatio);
  138 + int scale = src.file.get<float>("scale", 1);
  139 +
  140 + for (double y = 0; y + windowHeight < src.m().rows; y += stepSize) {
  141 + for (double x = 0; x + windowWidth < src.m().cols; x += stepSize) {
  142 + Rect window(x, y, windowWidth, windowHeight);
  143 + Template windowMat(src.file, Mat(src, window));
  144 + Template detect;
  145 + transform->project(windowMat, detect);
  146 + float conf = detect.file.get<float>("conf");
  147 +
  148 + // the result will be in the Label
  149 + if (conf > 0) {
  150 + dst.file.appendRect(QRectF((float) x * scale, (float) y * scale, (float) windowWidth * scale, (float) windowHeight * scale));
  151 + QList<float> confidences = dst.file.getList<float>("Confidences", QList<float>());
  152 + confidences.append(conf);
  153 + dst.file.setList<float>("Confidences", confidences);
  154 + if (takeFirst)
  155 + return;
  156 + }
  157 + }
  158 + }
  159 + }
  160 +
  161 + float aspectRatio;
  162 +};
  163 +
  164 +BR_REGISTER(Transform, SlidingWindowTransform)
  165 +
  166 +/*!
  167 + * \ingroup transforms
  168 + * \brief .
  169 + * \author Austin Blanton \cite imaus10
  170 + */
  171 +class BuildScalesTransform : public Transform
  172 +{
  173 + Q_OBJECT
  174 + Q_PROPERTY(br::Transform *transform READ get_transform WRITE set_transform RESET reset_transform STORED false)
  175 + Q_PROPERTY(double scaleFactor READ get_scaleFactor WRITE set_scaleFactor RESET reset_scaleFactor STORED false)
  176 + Q_PROPERTY(bool takeLargestScale READ get_takeLargestScale WRITE set_takeLargestScale RESET reset_takeLargestScale STORED false)
  177 + Q_PROPERTY(int windowWidth READ get_windowWidth WRITE set_windowWidth RESET reset_windowWidth STORED false)
  178 + BR_PROPERTY(br::Transform *, transform, NULL)
  179 + BR_PROPERTY(double, scaleFactor, 0.75)
  180 + BR_PROPERTY(bool, takeLargestScale, true)
  181 + BR_PROPERTY(int, windowWidth, 24)
  182 +
  183 +public:
  184 + BuildScalesTransform() : Transform(false, true) {}
  185 +private:
  186 +
  187 + void train(const TemplateList &data)
  188 + {
  189 + aspectRatio = getAspectRatio(data);
  190 + // have to make a copy b/c data is const
  191 + TemplateList cp = data;
  192 + cp.first().file.set("aspectRatio", aspectRatio);
  193 + if (transform->trainable)
  194 + transform->train(cp);
  195 + }
  196 +
  197 + void project(const Template &src, Template &dst) const
  198 + {
  199 + dst = src;
  200 + // do not scale images during training
  201 + if (src.file.getBool("Train", false)) return;
  202 +
135 203 int rows = src.m().rows;
136 204 int cols = src.m().cols;
137   - int windowHeight = (int) round((float) windowWidth / aspectRatio);
  205 + int windowHeight = (int) qRound((float) windowWidth / aspectRatio);
138 206 float startScale;
139 207 if ((cols / rows) > aspectRatio)
140   - startScale = round((float) rows / (float) windowHeight);
  208 + startScale = qRound((float) rows / (float) windowHeight);
141 209 else
142   - startScale = round((float) cols / (float) windowWidth);
143   -
  210 + startScale = qRound((float) cols / (float) windowWidth);
144 211 for (float scale = startScale; scale >= 1.0; scale -= (1.0 - scaleFactor)) {
145   - Mat scaleImg;
146   - resize(src, scaleImg, Size(round(cols / scale), round(rows / scale)));
147   -
148   - for (double y = 0; y + windowHeight < scaleImg.rows; y += stepSize) {
149   - for (double x = 0; x + windowWidth < scaleImg.cols; x += stepSize) {
150   - Rect window(x, y, windowWidth, windowHeight);
151   - Template windowMat(src.file, Mat(scaleImg, window));
152   - Template detect;
153   - transform->project(windowMat, detect);
154   - float conf = detect.file.get<float>("conf");
155   -
156   - // the result will be in the Label
157   - if (conf > 0) {
158   - dst.file.appendRect(QRectF((float) x * scale, (float) y * scale, (float) windowWidth * scale, (float) windowHeight * scale));
159   - QList<float> confidences = dst.file.getList<float>("Confidences", QList<float>());
160   - confidences.append(conf);
161   - dst.file.setList<float>("Confidences", confidences);
162   - if (takeLargestScale)
163   - return;
164   - }
165   - }
166   - }
  212 + Template scaleImg(src.file, Mat());
  213 + scaleImg.file.set("scale", scale);
  214 + resize(src, scaleImg, Size(qRound(cols / scale), qRound(rows / scale)));
  215 + transform->project(scaleImg, dst);
  216 + if (takeLargestScale && !dst.file.rects().empty())
  217 + return;
167 218 }
168 219 }
  220 +
  221 + float aspectRatio;
169 222 };
170 223  
171   -BR_REGISTER(Transform, SlidingWindowTransform)
  224 +BR_REGISTER(Transform, BuildScalesTransform)
172 225  
173 226 /*!
174 227 * \ingroup transforms
... ...
openbr/plugins/stasm4.cpp
... ... @@ -132,13 +132,16 @@ class StasmTransform : public UntrainableTransform
132 132  
133 133 if (!foundFace) {
134 134 qWarning("No face found in %s.", qPrintable(src.file.fileName()));
  135 + dst.file.set("FTE",true);
135 136 } else {
  137 + QList<QPointF> points;
136 138 for (int i = 0; i < nLandmarks; i++) {
137 139 QPointF point(landmarks[2 * i], landmarks[2 * i + 1]);
138   - dst.file.appendPoint(point);
139   - if (i == 38) dst.file.set("StasmRightEye",point);
140   - else if (i == 39) dst.file.set("StasmLeftEye", point);
  140 + points.append(point);
141 141 }
  142 + dst.file.set("StasmRightEye", points[38]);
  143 + dst.file.set("StasmLeftEye", points[39]);
  144 + dst.file.appendPoints(points);
142 145 }
143 146 }
144 147 };
... ...
openbr/plugins/template.cpp
... ... @@ -9,7 +9,7 @@ namespace br
9 9 * \brief Retains only the values for the keys listed, to reduce template size
10 10 * \author Scott Klum \cite sklum
11 11 */
12   -class RetainTransform : public UntrainableTransform
  12 +class KeepMetadataTransform : public UntrainableTransform
13 13 {
14 14 Q_OBJECT
15 15 Q_PROPERTY(QStringList keys READ get_keys WRITE set_keys RESET reset_keys STORED false)
... ... @@ -24,7 +24,7 @@ class RetainTransform : public UntrainableTransform
24 24 }
25 25 };
26 26  
27   -BR_REGISTER(Transform, RetainTransform)
  27 +BR_REGISTER(Transform, KeepMetadataTransform)
28 28  
29 29 /*!
30 30 * \ingroup transforms
... ...
openbr/plugins/validate.cpp
... ... @@ -255,7 +255,7 @@ class RejectDistance : public Distance
255 255 {
256 256 // We don't look at the query
257 257 (void) b;
258   -
  258 +
259 259 foreach (const QString &key, keys)
260 260 if ((rejectIfContains && a.file.contains(key)) || (!rejectIfContains && !a.file.contains(key)))
261 261 return -std::numeric_limits<float>::max();
... ...