Commit c1a1921a62621a0358b41c0c5950061e04bcec09

Authored by sklum
2 parents 3f40433a fe7a2c4d

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

openbr/openbr_plugin.cpp
... ... @@ -234,6 +234,11 @@ void File::appendRect(const QRectF &rect)
234 234 m_metadata["Rects"] = newRects;
235 235 }
236 236  
  237 +void File::appendRect(const Rect &rect)
  238 +{
  239 + appendRect(OpenCVUtils::fromRect(rect));
  240 +}
  241 +
237 242 void File::appendRects(const QList<QRectF> &rects)
238 243 {
239 244 QList<QVariant> newRects = m_metadata["Rects"].toList();
... ... @@ -242,6 +247,11 @@ void File::appendRects(const QList&lt;QRectF&gt; &amp;rects)
242 247 m_metadata["Rects"] = newRects;
243 248 }
244 249  
  250 +void File::appendRects(const QList<Rect> &rects)
  251 +{
  252 + appendRects(OpenCVUtils::fromRects(rects));
  253 +}
  254 +
245 255 /* File - private methods */
246 256 void File::init(const QString &file)
247 257 {
... ...
openbr/openbr_plugin.h
... ... @@ -41,8 +41,6 @@
41 41 #include <QVector>
42 42 #include <opencv2/core/core.hpp>
43 43 #include <openbr/openbr.h>
44   -#include <openbr/core/qtutils.h>
45   -#include <openbr/core/opencvutils.h>
46 44  
47 45 /*!
48 46 * \defgroup cpp_plugin_sdk C++ Plugin SDK
... ... @@ -222,7 +220,11 @@ struct BR_EXPORT File
222 220 template <typename T>
223 221 void setList(const QString &key, const QList<T> &value)
224 222 {
225   - set(key, QtUtils::toVariantList(value));
  223 + QVariantList variantList;
  224 + variantList.reserve(value.size());
  225 + foreach (const T &item, value)
  226 + variantList << item;
  227 + set(key, variantList);
226 228 }
227 229  
228 230 inline void remove(const QString &key) { m_metadata.remove(key); } /*!< \brief Remove the metadata key. */
... ... @@ -315,9 +317,9 @@ struct BR_EXPORT File
315 317 QList<QRectF> namedRects() const; /*!< \brief Returns rects convertible from metadata values. */
316 318 QList<QRectF> rects() const; /*!< \brief Returns the file's rects list. */
317 319 void appendRect(const QRectF &rect); /*!< \brief Adds a rect to the file's rect list. */
318   - void appendRect(const cv::Rect &rect) { appendRect(OpenCVUtils::fromRect(rect)); } /*!< \brief Adds a rect to the file's rect list. */
  320 + void appendRect(const cv::Rect &rect); /*!< \brief Adds a rect to the file's rect list. */
319 321 void appendRects(const QList<QRectF> &rects); /*!< \brief Adds rects to the file's rect list. */
320   - void appendRects(const QList<cv::Rect> &rects) { appendRects(OpenCVUtils::fromRects(rects)); } /*!< \brief Adds rects to the file's rect list. */
  322 + void appendRects(const QList<cv::Rect> &rects); /*!< \brief Adds rects to the file's rect list. */
321 323 inline void clearRects() { m_metadata["Rects"] = QList<QVariant>(); } /*!< \brief Clears the file's rect list. */
322 324 inline void setRects(const QList<QRectF> &rects) { clearRects(); appendRects(rects); } /*!< \brief Overwrites the file's rect list. */
323 325 inline void setRects(const QList<cv::Rect> &rects) { clearRects(); appendRects(rects); } /*!< \brief Overwrites the file's rect list. */
... ...
openbr/plugins/eigen3.cpp
... ... @@ -302,11 +302,13 @@ class LDATransform : public Transform
302 302 Q_PROPERTY(int directLDA READ get_directLDA WRITE set_directLDA RESET reset_directLDA STORED false)
303 303 Q_PROPERTY(float directDrop READ get_directDrop WRITE set_directDrop RESET reset_directDrop STORED false)
304 304 Q_PROPERTY(QString inputVariable READ get_inputVariable WRITE set_inputVariable RESET reset_inputVariable STORED false)
  305 + Q_PROPERTY(bool isBinary READ get_isBinary WRITE set_isBinary RESET reset_isBinary STORED false)
305 306 BR_PROPERTY(float, pcaKeep, 0.98)
306 307 BR_PROPERTY(bool, pcaWhiten, false)
307 308 BR_PROPERTY(int, directLDA, 0)
308 309 BR_PROPERTY(float, directDrop, 0.1)
309 310 BR_PROPERTY(QString, inputVariable, "Label")
  311 + BR_PROPERTY(bool, isBinary, false)
310 312  
311 313 int dimsOut;
312 314 Eigen::VectorXf mean;
... ... @@ -316,7 +318,6 @@ class LDATransform : public Transform
316 318 {
317 319 // creates "Label"
318 320 TemplateList trainingSet = TemplateList::relabel(_trainingSet, inputVariable);
319   -
320 321 int instances = trainingSet.size();
321 322  
322 323 // Perform PCA dimensionality reduction
... ... @@ -450,6 +451,34 @@ class LDATransform : public Transform
450 451 // Compute final projection matrix
451 452 projection = ((space2.eVecs.transpose() * space1.eVecs.transpose()) * pca.eVecs.transpose()).transpose();
452 453 dimsOut = dim2;
  454 +
  455 + if (isBinary) {
  456 + assert(dimsOut == 1);
  457 + TemplateList projected;
  458 + float posVal = 0;
  459 + float negVal = 0;
  460 + for (int i = 0; i < trainingSet.size(); i++) {
  461 + Template t;
  462 + project(trainingSet[i],t);
  463 + //Note: the positive class is assumed to be 0 b/c it will
  464 + // typically be the first gallery template in the TemplateList structure
  465 + if (classes[i] == 0)
  466 + posVal += t.m().at<float>(0,0);
  467 + else if (classes[i] == 1)
  468 + negVal += t.m().at<float>(0,0);
  469 + else
  470 + qFatal("Binary mode only supports two class problems.");
  471 + }
  472 + posVal /= classCounts[0];
  473 + negVal /= classCounts[1];
  474 +
  475 + if (posVal < negVal) {
  476 + //Ensure positive value is supposed to be > 0 after projection
  477 + Eigen::MatrixXf invert = Eigen::MatrixXf::Ones(dimsIn,1);
  478 + invert *= -1;
  479 + projection = invert.transpose() * projection;
  480 + }
  481 + }
453 482 }
454 483  
455 484 void project(const Template &src, Template &dst) const
... ... @@ -462,6 +491,10 @@ class LDATransform : public Transform
462 491  
463 492 // Do projection
464 493 outMap = projection.transpose() * (inMap - mean);
  494 +
  495 + if (isBinary) {
  496 + dst.file.set("conf",dst.m().at<float>(0,0));
  497 + }
465 498 }
466 499  
467 500 void store(QDataStream &stream) const
... ...
openbr/plugins/slidingwindow.cpp
... ... @@ -8,11 +8,29 @@
8 8  
9 9 using namespace cv;
10 10  
  11 +namespace br
  12 +{
  13 +
11 14 // Because MSVC doesn't provide a round() function in math.h
12 15 static int round(float x) { return (floor(x + 0.5)); }
13   -
14   -namespace br
  16 +// Find avg aspect ratio
  17 +static float getAspectRatio(const TemplateList &data)
15 18 {
  19 + double tempRatio = 0;
  20 + int ratioCnt = 0;
  21 +
  22 + foreach (const Template &tmpl, data) {
  23 + QList<Rect> posRects = OpenCVUtils::toRects(tmpl.file.rects());
  24 + foreach (const Rect &posRect, posRects) {
  25 + if (posRect.x + posRect.width >= tmpl.m().cols || posRect.y + posRect.height >= tmpl.m().rows || posRect.x < 0 || posRect.y < 0) {
  26 + continue;
  27 + }
  28 + tempRatio += (float)posRect.width / (float)posRect.height;
  29 + ratioCnt += 1;
  30 + }
  31 + }
  32 + return tempRatio / (double)ratioCnt;
  33 +}
16 34  
17 35 /*!
18 36 * \ingroup transforms
... ... @@ -25,23 +43,19 @@ class SlidingWindowTransform : public Transform
25 43 Q_OBJECT
26 44 Q_PROPERTY(br::Transform *transform READ get_transform WRITE set_transform RESET reset_transform STORED false)
27 45 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 46 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)
  47 + Q_PROPERTY(bool takeFirst READ get_takeFirst WRITE set_takeFirst RESET reset_takeFirst STORED false)
31 48 Q_PROPERTY(bool negSamples READ get_negSamples WRITE set_negSamples RESET reset_negSamples STORED false)
32 49 Q_PROPERTY(int negToPosRatio READ get_negToPosRatio WRITE set_negToPosRatio RESET reset_negToPosRatio STORED false)
33 50 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 51 Q_PROPERTY(int windowWidth READ get_windowWidth WRITE set_windowWidth RESET reset_windowWidth STORED false)
36 52 BR_PROPERTY(br::Transform *, transform, NULL)
37 53 BR_PROPERTY(int, minSize, 8)
38   - BR_PROPERTY(double, scaleFactor, 0.75)
39 54 BR_PROPERTY(int, stepSize, 1)
40   - BR_PROPERTY(bool, takeLargestScale, true)
  55 + BR_PROPERTY(bool, takeFirst, true)
41 56 BR_PROPERTY(bool, negSamples, true)
42 57 BR_PROPERTY(int, negToPosRatio, 1)
43 58 BR_PROPERTY(double, maxOverlap, 0)
44   - BR_PROPERTY(float, aspectRatio, 1)
45 59 BR_PROPERTY(int, windowWidth, 24)
46 60  
47 61 public:
... ... @@ -50,24 +64,14 @@ private:
50 64  
51 65 void train(const TemplateList &data)
52 66 {
  67 + // only calculate if the work hasn't been done
  68 + aspectRatio = data.first().file.get<float>("aspectRatio", -1);
  69 + if (aspectRatio == -1)
  70 + aspectRatio = getAspectRatio(data);
  71 +
53 72 if (transform->trainable) {
54   - double tempRatio = 0;
55   - int ratioCnt = 0;
56 73 TemplateList full;
57 74  
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 75 foreach (const Template &tmpl, data) {
72 76 QList<Rect> posRects = OpenCVUtils::toRects(tmpl.file.rects());
73 77 QList<Rect> negRects;
... ... @@ -132,6 +136,72 @@ private:
132 136 if (src.file.getBool("Train", false)) return;
133 137  
134 138 dst.file.clearRects();
  139 + int windowHeight = (int) round((float) windowWidth / aspectRatio);
  140 + int scale = src.file.get<float>("scale", 1);
  141 +
  142 + for (double y = 0; y + windowHeight < src.m().rows; y += stepSize) {
  143 + for (double x = 0; x + windowWidth < src.m().cols; x += stepSize) {
  144 + Rect window(x, y, windowWidth, windowHeight);
  145 + Template windowMat(src.file, Mat(src, window));
  146 + Template detect;
  147 + transform->project(windowMat, detect);
  148 + float conf = detect.file.get<float>("conf");
  149 +
  150 + // the result will be in the Label
  151 + if (conf > 0) {
  152 + dst.file.appendRect(QRectF((float) x * scale, (float) y * scale, (float) windowWidth * scale, (float) windowHeight * scale));
  153 + QList<float> confidences = dst.file.getList<float>("Confidences", QList<float>());
  154 + confidences.append(conf);
  155 + dst.file.setList<float>("Confidences", confidences);
  156 + if (takeFirst)
  157 + return;
  158 + }
  159 + }
  160 + }
  161 + }
  162 +
  163 + float aspectRatio;
  164 +};
  165 +
  166 +BR_REGISTER(Transform, SlidingWindowTransform)
  167 +
  168 +/*!
  169 + * \ingroup transforms
  170 + * \brief .
  171 + * \author Austin Blanton \cite imaus10
  172 + */
  173 +class BuildScalesTransform : public Transform
  174 +{
  175 + Q_OBJECT
  176 + Q_PROPERTY(br::Transform *transform READ get_transform WRITE set_transform RESET reset_transform STORED false)
  177 + Q_PROPERTY(double scaleFactor READ get_scaleFactor WRITE set_scaleFactor RESET reset_scaleFactor STORED false)
  178 + Q_PROPERTY(bool takeLargestScale READ get_takeLargestScale WRITE set_takeLargestScale RESET reset_takeLargestScale STORED false)
  179 + Q_PROPERTY(int windowWidth READ get_windowWidth WRITE set_windowWidth RESET reset_windowWidth STORED false)
  180 + BR_PROPERTY(br::Transform *, transform, NULL)
  181 + BR_PROPERTY(double, scaleFactor, 0.75)
  182 + BR_PROPERTY(bool, takeLargestScale, true)
  183 + BR_PROPERTY(int, windowWidth, 24)
  184 +
  185 +public:
  186 + BuildScalesTransform() : Transform(false, true) {}
  187 +private:
  188 +
  189 + void train(const TemplateList &data)
  190 + {
  191 + aspectRatio = getAspectRatio(data);
  192 + // have to make a copy b/c data is const
  193 + TemplateList cp = data;
  194 + cp.first().file.set("aspectRatio", aspectRatio);
  195 + if (transform->trainable)
  196 + transform->train(cp);
  197 + }
  198 +
  199 + void project(const Template &src, Template &dst) const
  200 + {
  201 + dst = src;
  202 + // do not scale images during training
  203 + if (src.file.getBool("Train", false)) return;
  204 +
135 205 int rows = src.m().rows;
136 206 int cols = src.m().cols;
137 207 int windowHeight = (int) round((float) windowWidth / aspectRatio);
... ... @@ -140,34 +210,20 @@ private:
140 210 startScale = round((float) rows / (float) windowHeight);
141 211 else
142 212 startScale = round((float) cols / (float) windowWidth);
143   -
144 213 for (float scale = startScale; scale >= 1.0; scale -= (1.0 - scaleFactor)) {
145   - Mat scaleImg;
  214 + Template scaleImg(src.file, Mat());
  215 + scaleImg.file.set("scale", scale);
146 216 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   -qDebug() << "x=" << x << "\ty=" << y;
151   - Rect window(x, y, windowWidth, windowHeight);
152   - Template windowMat(src.file, Mat(scaleImg, window));
153   - Template detect;
154   - transform->project(windowMat, detect);
155   - // the result will be in the Label
156   - if (detect.file.get<QString>("Label") == "pos") {
157   - dst.file.appendRect(QRectF((float) x * scale, (float) y * scale, (float) windowWidth * scale, (float) windowHeight * scale));
158   - float confidence = detect.file.get<float>("Dist");
159   - QList<float> confidences = dst.file.getList<float>("Confidences", QList<float>());
160   - confidences.append(confidence);
161   - dst.file.setList<float>("Confidences", confidences);
162   - if (takeLargestScale) return;
163   - }
164   - }
165   - }
  217 + transform->project(scaleImg, dst);
  218 + if (takeLargestScale && !dst.file.rects().empty())
  219 + return;
166 220 }
167 221 }
  222 +
  223 + float aspectRatio;
168 224 };
169 225  
170   -BR_REGISTER(Transform, SlidingWindowTransform)
  226 +BR_REGISTER(Transform, BuildScalesTransform)
171 227  
172 228 /*!
173 229 * \ingroup transforms
... ...
openbr/plugins/svm.cpp
... ... @@ -157,7 +157,7 @@ private:
157 157 dst = src;
158 158 float prediction = svm.predict(src.m().reshape(1, 1), returnDFVal);
159 159 if (returnDFVal) {
160   - dst.file.set("Dist", prediction);
  160 + dst.file.set("conf", prediction);
161 161 // positive values ==> first class
162 162 // negative values ==> second class
163 163 prediction = prediction > 0 ? 0 : 1;
... ...