Commit 7693fd5fbae647cd4d399904ddce0b20a55b2bc4

Authored by Scott Klum
2 parents aca7accd 835f64e8

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

CMakeLists.txt
@@ -159,7 +159,7 @@ endif() @@ -159,7 +159,7 @@ endif()
159 # Download the models 159 # Download the models
160 ExternalProject_Add(models 160 ExternalProject_Add(models
161 URL http://github.com/biometrics/openbr/releases/download/v1.1.0/models.tar.gz 161 URL http://github.com/biometrics/openbr/releases/download/v1.1.0/models.tar.gz
162 - URL_MD5 22b158958907e08e611f11b1c62547c6 162 + URL_MD5 26cf71abd48cec8d7b2abf3e8f4ebfc4
163 SOURCE_DIR "${PROJECT_SOURCE_DIR}/share/openbr/models" 163 SOURCE_DIR "${PROJECT_SOURCE_DIR}/share/openbr/models"
164 CONFIGURE_COMMAND "" 164 CONFIGURE_COMMAND ""
165 BUILD_COMMAND "" 165 BUILD_COMMAND ""
openbr/core/boost.cpp
@@ -131,23 +131,16 @@ static CvMat* cvPreprocessIndexArray( const CvMat* idx_arr, int data_arr_size, b @@ -131,23 +131,16 @@ static CvMat* cvPreprocessIndexArray( const CvMat* idx_arr, int data_arr_size, b
131 131
132 //------------------------------------- FeatureEvaluator --------------------------------------- 132 //------------------------------------- FeatureEvaluator ---------------------------------------
133 133
134 -void FeatureEvaluator::init(Representation *_representation, int _maxSampleCount, int channels) 134 +void FeatureEvaluator::init(Representation *_representation, int _maxSampleCount)
135 { 135 {
136 representation = _representation; 136 representation = _representation;
137 -  
138 - int dx, dy;  
139 - Size windowSize = representation->windowSize(&dx, &dy);  
140 - data.create((int)_maxSampleCount, (windowSize.width + dx) * (windowSize.height + dy), CV_32SC(channels));  
141 cls.create( (int)_maxSampleCount, 1, CV_32FC1 ); 137 cls.create( (int)_maxSampleCount, 1, CV_32FC1 );
142 } 138 }
143 139
144 -void FeatureEvaluator::setImage(const Mat &img, uchar clsLabel, int idx) 140 +void FeatureEvaluator::setImage(const Template &src, uchar clsLabel, int idx)
145 { 141 {
146 cls.ptr<float>(idx)[0] = clsLabel; 142 cls.ptr<float>(idx)[0] = clsLabel;
147 -  
148 - Mat pp;  
149 - representation->preprocess(img, pp);  
150 - pp.reshape(0, 1).copyTo(data.row(idx)); 143 + data.append(representation->preprocess(src));
151 } 144 }
152 145
153 //----------------------------- CascadeBoostParams ------------------------------------------------- 146 //----------------------------- CascadeBoostParams -------------------------------------------------
openbr/core/boost.h
@@ -2,7 +2,6 @@ @@ -2,7 +2,6 @@
2 #define _BOOST_H_ 2 #define _BOOST_H_
3 3
4 #include "ml.h" 4 #include "ml.h"
5 -#include <time.h>  
6 #include <openbr/openbr_plugin.h> 5 #include <openbr/openbr_plugin.h>
7 6
8 #ifdef _WIN32 7 #ifdef _WIN32
@@ -17,9 +16,9 @@ namespace br @@ -17,9 +16,9 @@ namespace br
17 struct FeatureEvaluator 16 struct FeatureEvaluator
18 { 17 {
19 ~FeatureEvaluator() {} 18 ~FeatureEvaluator() {}
20 - void init(Representation *_representation, int _maxSampleCount, int channels);  
21 - void setImage(const cv::Mat& img, uchar clsLabel, int idx);  
22 - float operator()(int featureIdx, int sampleIdx) const { return representation->evaluate(data.row(sampleIdx), featureIdx); } 19 + void init(Representation *_representation, int _maxSampleCount);
  20 + void setImage(const Template &src, uchar clsLabel, int idx);
  21 + float operator()(int featureIdx, int sampleIdx) const { return representation->evaluate(data[sampleIdx], featureIdx); }
23 22
24 int getNumFeatures() const { return representation->numFeatures(); } 23 int getNumFeatures() const { return representation->numFeatures(); }
25 int getMaxCatCount() const { return representation->maxCatCount(); } 24 int getMaxCatCount() const { return representation->maxCatCount(); }
@@ -27,7 +26,8 @@ struct FeatureEvaluator @@ -27,7 +26,8 @@ struct FeatureEvaluator
27 const cv::Mat& getCls() const { return cls; } 26 const cv::Mat& getCls() const { return cls; }
28 float getCls(int si) const { return cls.at<float>(si, 0); } 27 float getCls(int si) const { return cls.at<float>(si, 0); }
29 28
30 - cv::Mat data, cls; 29 + cv::Mat cls;
  30 + TemplateList data;
31 Representation *representation; 31 Representation *representation;
32 }; 32 };
33 33
openbr/openbr_plugin.h
@@ -882,13 +882,11 @@ public: @@ -882,13 +882,11 @@ public:
882 882
883 static Representation *make(QString str, QObject *parent); /*!< \brief Make a representation from a string. */ 883 static Representation *make(QString str, QObject *parent); /*!< \brief Make a representation from a string. */
884 884
885 - virtual void preprocess(const cv::Mat &src, cv::Mat &dst) const { dst = src; }  
886 - virtual void train(const QList<cv::Mat> &images, const QList<float> &labels) { (void) images; (void)labels; }  
887 -  
888 - virtual float evaluate(const cv::Mat &image, int idx) const = 0;  
889 - // By convention, an empty indices list will result in all feature responses being calculated  
890 - // and returned.  
891 - virtual cv::Mat evaluate(const cv::Mat &image, const QList<int> &indices = QList<int>()) const = 0; 885 + virtual Template preprocess(const Template &src) const { return src; }
  886 + virtual void train(const TemplateList &data) { (void)data; }
  887 + virtual float evaluate(const Template &src, int idx) const = 0;
  888 + // By convention passing an empty list evaluates all features in the representation
  889 + virtual cv::Mat evaluate(const Template &src, const QList<int> &indices = QList<int>()) const = 0;
892 890
893 virtual cv::Size windowSize(int *dx = NULL, int *dy = NULL) const = 0; // dx and dy should indicate the change to the original window size after preprocessing 891 virtual cv::Size windowSize(int *dx = NULL, int *dy = NULL) const = 0; // dx and dy should indicate the change to the original window size after preprocessing
894 virtual int numChannels() const { return 1; } 892 virtual int numChannels() const { return 1; }
@@ -905,13 +903,13 @@ public: @@ -905,13 +903,13 @@ public:
905 903
906 static Classifier *make(QString str, QObject *parent); 904 static Classifier *make(QString str, QObject *parent);
907 905
908 - virtual void train(const QList<cv::Mat> &images, const QList<float> &labels) = 0;  
909 - virtual float classify(const cv::Mat &image, bool process = true, float *confidence = NULL) const = 0; 906 + virtual void train(const TemplateList &data) { (void)data; }
  907 + virtual float classify(const Template &src, bool process = true, float *confidence = NULL) const = 0;
910 908
911 // Slots for representations 909 // Slots for representations
912 - virtual cv::Mat preprocess(const cv::Mat &image) const = 0; 910 + virtual Template preprocess(const Template &src) const { return src; }
913 virtual cv::Size windowSize(int *dx = NULL, int *dy = NULL) const = 0; 911 virtual cv::Size windowSize(int *dx = NULL, int *dy = NULL) const = 0;
914 - virtual int numFeatures() const = 0; 912 + virtual int numFeatures() const { return 0; }
915 }; 913 };
916 914
917 915
openbr/plugins/classification/boostedforest.cpp
@@ -125,20 +125,20 @@ private: @@ -125,20 +125,20 @@ private:
125 QList<Node*> classifiers; 125 QList<Node*> classifiers;
126 float threshold; 126 float threshold;
127 127
128 - void train(const QList<Mat> &images, const QList<float> &labels) 128 + void train(const TemplateList &data)
129 { 129 {
130 - representation->train(images, labels); 130 + representation->train(data);
131 131
132 CascadeBoostParams params(type, minTAR, maxFAR, trimRate, maxDepth, maxWeakCount); 132 CascadeBoostParams params(type, minTAR, maxFAR, trimRate, maxDepth, maxWeakCount);
133 133
134 FeatureEvaluator featureEvaluator; 134 FeatureEvaluator featureEvaluator;
135 - featureEvaluator.init(representation, images.size(), representation->numChannels()); 135 + featureEvaluator.init(representation, data.size());
136 136
137 - for (int i = 0; i < images.size(); i++)  
138 - featureEvaluator.setImage(images[i], labels[i], i); 137 + for (int i = 0; i < data.size(); i++)
  138 + featureEvaluator.setImage(data[i], data[i].file.get<float>("Label"), i);
139 139
140 CascadeBoost boost; 140 CascadeBoost boost;
141 - boost.train(&featureEvaluator, images.size(), 1024, 1024, representation->numChannels(), params); 141 + boost.train(&featureEvaluator, data.size(), 1024, 1024, representation->numChannels(), params);
142 142
143 threshold = boost.getThreshold(); 143 threshold = boost.getThreshold();
144 144
@@ -149,13 +149,9 @@ private: @@ -149,13 +149,9 @@ private:
149 } 149 }
150 } 150 }
151 151
152 - float classify(const Mat &image, bool process, float *confidence) const 152 + float classify(const Template &src, bool process, float *confidence) const
153 { 153 {
154 - Mat m;  
155 - if (process)  
156 - m = preprocess(image);  
157 - else  
158 - m = image; 154 + Template t = process ? preprocess(src) : src;
159 155
160 float sum = 0; 156 float sum = 0;
161 for (int i = 0; i < classifiers.size(); i++) { 157 for (int i = 0; i < classifiers.size(); i++) {
@@ -163,10 +159,10 @@ private: @@ -163,10 +159,10 @@ private:
163 159
164 while (node->left) { 160 while (node->left) {
165 if (representation->maxCatCount() > 0) { 161 if (representation->maxCatCount() > 0) {
166 - int c = (int)representation->evaluate(m, node->featureIdx); 162 + int c = (int)representation->evaluate(t, node->featureIdx);
167 node = (node->subset[c >> 5] & (1 << (c & 31))) ? node->left : node->right; 163 node = (node->subset[c >> 5] & (1 << (c & 31))) ? node->left : node->right;
168 } else { 164 } else {
169 - double val = representation->evaluate(m, node->featureIdx); 165 + double val = representation->evaluate(t, node->featureIdx);
170 node = val <= node->threshold ? node->left : node->right; 166 node = val <= node->threshold ? node->left : node->right;
171 } 167 }
172 } 168 }
@@ -184,11 +180,9 @@ private: @@ -184,11 +180,9 @@ private:
184 return representation->numFeatures(); 180 return representation->numFeatures();
185 } 181 }
186 182
187 - Mat preprocess(const Mat &image) const 183 + Template preprocess(const Template &src) const
188 { 184 {
189 - Mat dst;  
190 - representation->preprocess(image, dst);  
191 - return dst; 185 + return representation->preprocess(src);
192 } 186 }
193 187
194 Size windowSize(int *dx, int *dy) const 188 Size windowSize(int *dx, int *dy) const
openbr/plugins/classification/cascade.cpp
1 #include <opencv2/imgproc/imgproc.hpp> 1 #include <opencv2/imgproc/imgproc.hpp>
2 -#include <opencv2/highgui/highgui.hpp> 2 +
3 #include <openbr/plugins/openbr_internal.h> 3 #include <openbr/plugins/openbr_internal.h>
4 #include <openbr/core/common.h> 4 #include <openbr/core/common.h>
5 #include "openbr/core/opencvutils.h" 5 #include "openbr/core/opencvutils.h"
@@ -101,8 +101,8 @@ class CascadeClassifier : public Classifier @@ -101,8 +101,8 @@ class CascadeClassifier : public Classifier
101 BR_PROPERTY(bool, requireAllStages, false) 101 BR_PROPERTY(bool, requireAllStages, false)
102 102
103 QList<Classifier *> stages; 103 QList<Classifier *> stages;
104 - QList<Mat> posImages, negImages;  
105 - QList<Mat> posSamples, negSamples; 104 + TemplateList posImages, negImages;
  105 + TemplateList posSamples, negSamples;
106 106
107 QList<int> indices; 107 QList<int> indices;
108 int negIndex, posIndex, samplingRound; 108 int negIndex, posIndex, samplingRound;
@@ -114,18 +114,17 @@ class CascadeClassifier : public Classifier @@ -114,18 +114,17 @@ class CascadeClassifier : public Classifier
114 negIndex = posIndex = samplingRound = 0; 114 negIndex = posIndex = samplingRound = 0;
115 } 115 }
116 116
117 - bool getPositive(Mat &img) 117 + bool getPositive(Template &img)
118 { 118 {
119 if (posIndex >= posImages.size()) 119 if (posIndex >= posImages.size())
120 return false; 120 return false;
121 -  
122 - posImages[indices[posIndex++]].copyTo(img); 121 + img = posImages[indices[posIndex++]];
123 return true; 122 return true;
124 } 123 }
125 124
126 - Mat getNegative(Point &offset) 125 + Template getNegative(Point &offset)
127 { 126 {
128 - Mat negative; 127 + Template negative;
129 128
130 const Size size = windowSize(); 129 const Size size = windowSize();
131 // Grab negative from list 130 // Grab negative from list
@@ -137,9 +136,9 @@ class CascadeClassifier : public Classifier @@ -137,9 +136,9 @@ class CascadeClassifier : public Classifier
137 samplingRound = samplingRound % (size.width * size.height); 136 samplingRound = samplingRound % (size.width * size.height);
138 negIndex %= count; 137 negIndex %= count;
139 138
140 - offset.x = qMin( (int)samplingRound % size.width, negative.cols - size.width);  
141 - offset.y = qMin( (int)samplingRound / size.width, negative.rows - size.height);  
142 - if (!negative.empty() && negative.type() == CV_8U 139 + offset.x = qMin( (int)samplingRound % size.width, negative.m().cols - size.width);
  140 + offset.y = qMin( (int)samplingRound / size.width, negative.m().rows - size.height);
  141 + if (!negative.m().empty() && negative.m().type() == CV_8U
143 && offset.x >= 0 && offset.y >= 0) 142 && offset.x >= 0 && offset.y >= 0)
144 break; 143 break;
145 } 144 }
@@ -151,16 +150,16 @@ class CascadeClassifier : public Classifier @@ -151,16 +150,16 @@ class CascadeClassifier : public Classifier
151 { 150 {
152 uint64 passedNegatives = 0; 151 uint64 passedNegatives = 0;
153 forever { 152 forever {
154 - Mat negative; 153 + Template negative;
155 Point offset; 154 Point offset;
156 QMutexLocker samplingLocker(&samplingMutex); 155 QMutexLocker samplingLocker(&samplingMutex);
157 negative = getNegative(offset); 156 negative = getNegative(offset);
158 samplingLocker.unlock(); 157 samplingLocker.unlock();
159 158
160 - Miner miner(negative, windowSize(), offset); 159 + Miner miner(negative.m(), windowSize(), offset);
161 forever { 160 forever {
162 bool newImg; 161 bool newImg;
163 - Mat sample = miner.mine(&newImg); 162 + Template sample(negative.file, miner.mine(&newImg));
164 if (!newImg) { 163 if (!newImg) {
165 if (negSamples.size() >= numNegs) 164 if (negSamples.size() >= numNegs)
166 return passedNegatives; 165 return passedNegatives;
@@ -182,16 +181,16 @@ class CascadeClassifier : public Classifier @@ -182,16 +181,16 @@ class CascadeClassifier : public Classifier
182 } 181 }
183 } 182 }
184 183
185 - void train(const QList<Mat> &images, const QList<float> &labels) 184 + void train(const TemplateList &data)
186 { 185 {
187 - for (int i = 0; i < images.size(); i++)  
188 - labels[i] == 1 ? posImages.append(images[i]) : negImages.append(images[i]); 186 + foreach (const Template &t, data)
  187 + t.file.get<float>("Label") == 1.0f ? posImages.append(t) : negImages.append(t);
189 188
190 - qDebug() << "Total images:" << images.size() 189 + qDebug() << "Total images:" << data.size()
191 << "\nTotal positive images:" << posImages.size() 190 << "\nTotal positive images:" << posImages.size()
192 << "\nTotal negative images:" << negImages.size(); 191 << "\nTotal negative images:" << negImages.size();
193 192
194 - indices = Common::RandSample(posImages.size(),posImages.size(),true); 193 + indices = Common::RandSample(posImages.size(), posImages.size(), true);
195 194
196 stages.reserve(numStages); 195 stages.reserve(numStages);
197 for (int i = 0; i < numStages; i++) { 196 for (int i = 0; i < numStages; i++) {
@@ -210,27 +209,17 @@ class CascadeClassifier : public Classifier @@ -210,27 +209,17 @@ class CascadeClassifier : public Classifier
210 return; 209 return;
211 } 210 }
212 211
213 - QList<float> posLabels;  
214 - posLabels.reserve(posSamples.size());  
215 - for (int j=0; j<posSamples.size(); j++)  
216 - posLabels.append(1);  
217 -  
218 - QList<float> negLabels;  
219 - negLabels.reserve(negSamples.size());  
220 - for (int j=0; j<negSamples.size(); j++)  
221 - negLabels.append(0);  
222 -  
223 - stages[i]->train(posSamples+negSamples, posLabels+negLabels); 212 + stages[i]->train(posSamples + negSamples);
224 213
225 qDebug() << "END>"; 214 qDebug() << "END>";
226 } 215 }
227 } 216 }
228 217
229 - float classify(const Mat &image, bool process, float *confidence) const 218 + float classify(const Template &src, bool process, float *confidence) const
230 { 219 {
231 float stageConf = 0.0f; 220 float stageConf = 0.0f;
232 foreach (const Classifier *stage, stages) { 221 foreach (const Classifier *stage, stages) {
233 - float result = stage->classify(image, process, &stageConf); 222 + float result = stage->classify(src, process, &stageConf);
234 if (confidence) 223 if (confidence)
235 *confidence += stageConf; 224 *confidence += stageConf;
236 if (result == 0.0f) 225 if (result == 0.0f)
@@ -244,9 +233,9 @@ class CascadeClassifier : public Classifier @@ -244,9 +233,9 @@ class CascadeClassifier : public Classifier
244 return stages.first()->numFeatures(); 233 return stages.first()->numFeatures();
245 } 234 }
246 235
247 - Mat preprocess(const Mat &image) const 236 + Template preprocess(const Template &src) const
248 { 237 {
249 - return stages.first()->preprocess(image); 238 + return stages.first()->preprocess(src);
250 } 239 }
251 240
252 Size windowSize(int *dx = NULL, int *dy = NULL) const 241 Size windowSize(int *dx = NULL, int *dy = NULL) const
@@ -274,16 +263,13 @@ class CascadeClassifier : public Classifier @@ -274,16 +263,13 @@ class CascadeClassifier : public Classifier
274 private: 263 private:
275 float getSamples() 264 float getSamples()
276 { 265 {
277 - posSamples.clear();  
278 - posSamples.reserve(numPos);  
279 - negSamples.clear();  
280 - negSamples.reserve(numNegs); 266 + posSamples.clear(); posSamples.reserve(numPos);
  267 + negSamples.clear(); negSamples.reserve(numNegs);
281 posIndex = 0; 268 posIndex = 0;
282 269
283 float confidence; 270 float confidence;
284 while (posSamples.size() < numPos) { 271 while (posSamples.size() < numPos) {
285 - Mat pos(windowSize(), CV_8U);  
286 - 272 + Template pos;
287 if (!getPositive(pos)) 273 if (!getPositive(pos))
288 qFatal("Cannot get another positive sample!"); 274 qFatal("Cannot get another positive sample!");
289 275
openbr/plugins/classification/liblinear.cpp
@@ -138,7 +138,7 @@ private: @@ -138,7 +138,7 @@ private:
138 param.weight = NULL; 138 param.weight = NULL;
139 } 139 }
140 140
141 - m = *train_svm(&prob, &param); 141 + //m = *train_svm(&prob, &param);
142 142
143 delete[] param.weight; 143 delete[] param.weight;
144 delete[] param.weight_label; 144 delete[] param.weight_label;
openbr/plugins/imgproc/slidingwindow.cpp
@@ -17,7 +17,6 @@ @@ -17,7 +17,6 @@
17 #include <openbr/plugins/openbr_internal.h> 17 #include <openbr/plugins/openbr_internal.h>
18 #include <openbr/core/opencvutils.h> 18 #include <openbr/core/opencvutils.h>
19 #include <openbr/core/qtutils.h> 19 #include <openbr/core/qtutils.h>
20 -#include <opencv2/highgui/highgui.hpp>  
21 20
22 #include <opencv2/imgproc/imgproc.hpp> 21 #include <opencv2/imgproc/imgproc.hpp>
23 22
@@ -35,7 +34,6 @@ namespace br @@ -35,7 +34,6 @@ namespace br
35 * \br_property int minSize The smallest sized object to detect in pixels 34 * \br_property int minSize The smallest sized object to detect in pixels
36 * \br_property int maxSize The largest sized object to detect in pixels. A negative value will set maxSize == image size 35 * \br_property int maxSize The largest sized object to detect in pixels. A negative value will set maxSize == image size
37 * \br_property float scaleFactor The factor to scale the image by during each resize. 36 * \br_property float scaleFactor The factor to scale the image by during each resize.
38 - * \br_property int minNeighbors Parameter for non-maximum supression  
39 * \br_property float confidenceThreshold A threshold for positive detections. Positive detections returned by the classifier that have confidences below this threshold are considered negative detections. 37 * \br_property float confidenceThreshold A threshold for positive detections. Positive detections returned by the classifier that have confidences below this threshold are considered negative detections.
40 * \br_property float eps Parameter for non-maximum supression 38 * \br_property float eps Parameter for non-maximum supression
41 */ 39 */
@@ -60,7 +58,7 @@ class SlidingWindowTransform : public MetaTransform @@ -60,7 +58,7 @@ class SlidingWindowTransform : public MetaTransform
60 58
61 void train(const TemplateList &data) 59 void train(const TemplateList &data)
62 { 60 {
63 - classifier->train(data.data(), File::get<float>(data, "Label", -1)); 61 + classifier->train(data);
64 } 62 }
65 63
66 void project(const Template &src, Template &dst) const 64 void project(const Template &src, Template &dst) const
@@ -123,15 +121,18 @@ class SlidingWindowTransform : public MetaTransform @@ -123,15 +121,18 @@ class SlidingWindowTransform : public MetaTransform
123 121
124 Mat scaledImage(scaledImageSize, CV_8U, imageBuffer.data); 122 Mat scaledImage(scaledImageSize, CV_8U, imageBuffer.data);
125 resize(m, scaledImage, scaledImageSize, 0, 0, CV_INTER_LINEAR); 123 resize(m, scaledImage, scaledImageSize, 0, 0, CV_INTER_LINEAR);
126 - Mat repImage = classifier->preprocess(scaledImage); 124 +
  125 + Template repImage(t.file, scaledImage);
  126 + repImage = classifier->preprocess(repImage);
127 127
128 int step = factor > 2. ? 1 : 2; 128 int step = factor > 2. ? 1 : 2;
129 for (int y = 0; y < processingRectSize.height; y += step) { 129 for (int y = 0; y < processingRectSize.height; y += step) {
130 for (int x = 0; x < processingRectSize.width; x += step) { 130 for (int x = 0; x < processingRectSize.width; x += step) {
131 - Mat window = repImage(Rect(Point(x, y), Size(originalWindowSize.width + dx, originalWindowSize.height + dy))).clone(); 131 + Mat window = repImage.m()(Rect(Point(x, y), Size(originalWindowSize.width + dx, originalWindowSize.height + dy))).clone();
  132 + Template t(window);
132 133
133 float confidence = 0; 134 float confidence = 0;
134 - int result = classifier->classify(window, false, &confidence); 135 + int result = classifier->classify(t, false, &confidence);
135 136
136 if (result == 1) { 137 if (result == 1) {
137 rects.append(Rect(cvRound(x*factor), cvRound(y*factor), windowSize.width, windowSize.height)); 138 rects.append(Rect(cvRound(x*factor), cvRound(y*factor), windowSize.width, windowSize.height));
openbr/plugins/metadata/cascade.cpp
@@ -413,6 +413,17 @@ class CascadeTransform : public MetaTransform @@ -413,6 +413,17 @@ class CascadeTransform : public MetaTransform
413 if (ROCMode) cascade->detectMultiScale(m, rects, rejectLevels, levelWeights, 1.2, minNeighbors, flags | CASCADE_SCALE_IMAGE, Size(minSize, minSize), Size(), true); 413 if (ROCMode) cascade->detectMultiScale(m, rects, rejectLevels, levelWeights, 1.2, minNeighbors, flags | CASCADE_SCALE_IMAGE, Size(minSize, minSize), Size(), true);
414 else cascade->detectMultiScale(m, rects, 1.2, minNeighbors, flags, Size(minSize, minSize)); 414 else cascade->detectMultiScale(m, rects, 1.2, minNeighbors, flags, Size(minSize, minSize));
415 415
  416 + // It appears that flags is ignored for new model files:
  417 + // http://docs.opencv.org/modules/objdetect/doc/cascade_classification.html#cascadeclassifier-detectmultiscale
  418 + if ((flags == CASCADE_FIND_BIGGEST_OBJECT) && (rects.size() > 1)) {
  419 + Rect biggest = rects[0];
  420 + for (size_t j=0; j<rects.size(); j++)
  421 + if (rects[j].area() > biggest.area())
  422 + biggest = rects[j];
  423 + rects.clear();
  424 + rects.push_back(biggest);
  425 + }
  426 +
416 bool empty = false; 427 bool empty = false;
417 if (!enrollAll && rects.empty()) { 428 if (!enrollAll && rects.empty()) {
418 empty = true; 429 empty = true;
openbr/plugins/representation/haar.cpp
@@ -80,23 +80,25 @@ class HaarRepresentation : public Representation @@ -80,23 +80,25 @@ class HaarRepresentation : public Representation
80 } 80 }
81 } 81 }
82 82
83 - void preprocess(const Mat &src, Mat &dst) const 83 + Template preprocess(const Template &src) const
84 { 84 {
  85 + Template dst;
85 integral(src, dst); 86 integral(src, dst);
  87 + return dst;
86 } 88 }
87 89
88 - float evaluate(const Mat &image, int idx) const 90 + float evaluate(const Template &src, int idx) const
89 { 91 {
90 - return (float)features[idx].calc(image); 92 + return (float)features[idx].calc(src.m());
91 } 93 }
92 94
93 - Mat evaluate(const Mat &image, const QList<int> &indices) const 95 + Mat evaluate(const Template &src, const QList<int> &indices) const
94 { 96 {
95 int size = indices.empty() ? numFeatures() : indices.size(); 97 int size = indices.empty() ? numFeatures() : indices.size();
96 98
97 Mat result(1, size, CV_32FC1); 99 Mat result(1, size, CV_32FC1);
98 for (int i = 0; i < size; i++) 100 for (int i = 0; i < size; i++)
99 - result.at<float>(i) = evaluate(image, indices.empty() ? i : indices[i]); 101 + result.at<float>(i) = evaluate(src, indices.empty() ? i : indices[i]);
100 return result; 102 return result;
101 } 103 }
102 104
openbr/plugins/representation/mblbp.cpp
@@ -39,32 +39,36 @@ class MBLBPRepresentation : public Representation @@ -39,32 +39,36 @@ class MBLBPRepresentation : public Representation
39 39
40 void init() 40 void init()
41 { 41 {
42 - int offset = winWidth + 1;  
43 - for (int x = 0; x < winWidth; x++ )  
44 - for (int y = 0; y < winHeight; y++ )  
45 - for (int w = 1; w <= winWidth / 3; w++ )  
46 - for (int h = 1; h <= winHeight / 3; h++ )  
47 - if ((x+3*w <= winWidth) && (y+3*h <= winHeight) )  
48 - features.append(Feature(offset, x, y, w, h ) ); 42 + if (features.isEmpty()) {
  43 + int offset = winWidth + 1;
  44 + for (int x = 0; x < winWidth; x++ )
  45 + for (int y = 0; y < winHeight; y++ )
  46 + for (int w = 1; w <= winWidth / 3; w++ )
  47 + for (int h = 1; h <= winHeight / 3; h++ )
  48 + if ((x+3*w <= winWidth) && (y+3*h <= winHeight) )
  49 + features.append(Feature(offset, x, y, w, h ) );
  50 + }
49 } 51 }
50 52
51 - void preprocess(const Mat &src, Mat &dst) const 53 + Template preprocess(const Template &src) const
52 { 54 {
  55 + Template dst;
53 integral(src, dst); 56 integral(src, dst);
  57 + return dst;
54 } 58 }
55 59
56 - float evaluate(const Mat &image, int idx) const 60 + float evaluate(const Template &src, int idx) const
57 { 61 {
58 - return (float)features[idx].calc(image); 62 + return (float)features[idx].calc(src.m());
59 } 63 }
60 64
61 - Mat evaluate(const Mat &image, const QList<int> &indices) const 65 + Mat evaluate(const Template &src, const QList<int> &indices) const
62 { 66 {
63 int size = indices.empty() ? numFeatures() : indices.size(); 67 int size = indices.empty() ? numFeatures() : indices.size();
64 68
65 Mat result(1, size, CV_32FC1); 69 Mat result(1, size, CV_32FC1);
66 for (int i = 0; i < size; i++) 70 for (int i = 0; i < size; i++)
67 - result.at<float>(i) = evaluate(image, indices.empty() ? i : indices[i]); 71 + result.at<float>(i) = evaluate(src, indices.empty() ? i : indices[i]);
68 return result; 72 return result;
69 } 73 }
70 74
openbr/plugins/representation/npd.cpp
@@ -16,23 +16,25 @@ class NPDRepresentation : public Representation @@ -16,23 +16,25 @@ class NPDRepresentation : public Representation
16 16
17 void init() 17 void init()
18 { 18 {
19 - for (int p1 = 0; p1 < (winWidth * winHeight); p1++)  
20 - for (int p2 = p1; p2 < (winWidth * winHeight); p2++)  
21 - features.append(Feature(p1, p2)); 19 + if (features.isEmpty()) {
  20 + for (int p1 = 0; p1 < (winWidth * winHeight); p1++)
  21 + for (int p2 = p1; p2 < (winWidth * winHeight); p2++)
  22 + features.append(Feature(p1, p2));
  23 + }
22 } 24 }
23 25
24 - float evaluate(const Mat &image, int idx) const 26 + float evaluate(const Template &src, int idx) const
25 { 27 {
26 - return features[idx].calc(image); 28 + return features[idx].calc(src.m());
27 } 29 }
28 30
29 - Mat evaluate(const Mat &image, const QList<int> &indices) const 31 + Mat evaluate(const Template &src, const QList<int> &indices) const
30 { 32 {
31 int size = indices.empty() ? numFeatures() : indices.size(); 33 int size = indices.empty() ? numFeatures() : indices.size();
32 34
33 Mat result(1, size, CV_32FC1); 35 Mat result(1, size, CV_32FC1);
34 for (int i = 0; i < size; i++) 36 for (int i = 0; i < size; i++)
35 - result.at<float>(i) = evaluate(image, indices.empty() ? i : indices[i]); 37 + result.at<float>(i) = evaluate(src, indices.empty() ? i : indices[i]);
36 return result; 38 return result;
37 } 39 }
38 40
@@ -49,10 +51,10 @@ class NPDRepresentation : public Representation @@ -49,10 +51,10 @@ class NPDRepresentation : public Representation
49 struct Feature 51 struct Feature
50 { 52 {
51 Feature() {} 53 Feature() {}
52 - Feature(int p1, int p2) { p[0] = p1; p[1] = p2; } 54 + Feature(int p0, int p1) : p0(p0), p1(p1) {}
53 float calc(const Mat &image) const; 55 float calc(const Mat &image) const;
54 56
55 - int p[2]; 57 + int p0, p1;
56 }; 58 };
57 QList<Feature> features; 59 QList<Feature> features;
58 }; 60 };
@@ -61,9 +63,9 @@ BR_REGISTER(Representation, NPDRepresentation) @@ -61,9 +63,9 @@ BR_REGISTER(Representation, NPDRepresentation)
61 63
62 inline float NPDRepresentation::Feature::calc(const Mat &image) const 64 inline float NPDRepresentation::Feature::calc(const Mat &image) const
63 { 65 {
64 - const int *ptr = image.ptr<int>();  
65 - int v1 = ptr[p[0]], v2 = ptr[p[1]];  
66 - return v1 == 0 && v2 == 0 ? 0 : ((float)(v1 - v2)) / (v1 + v2); 66 + const uchar *ptr = image.ptr();
  67 + int v1 = (int)ptr[p0], v2 = (int)ptr[p1];
  68 + return (v1 + v2) == 0 ? 0 : (1.0 * (v1 - v2)) / (v1 + v2);
67 } 69 }
68 70
69 } // namespace br 71 } // namespace br
openbr/plugins/representation/random.cpp
@@ -28,9 +28,9 @@ class RandomRepresentation : public Representation @@ -28,9 +28,9 @@ class RandomRepresentation : public Representation
28 28
29 QList<int> features; 29 QList<int> features;
30 30
31 - void train(const QList<Mat> &images, const QList<float> &labels) 31 + void train(const TemplateList &data)
32 { 32 {
33 - representation->train(images, labels); 33 + representation->train(data);
34 34
35 const int nFeatures = representation->numFeatures(); 35 const int nFeatures = representation->numFeatures();
36 36
@@ -40,17 +40,17 @@ class RandomRepresentation : public Representation @@ -40,17 +40,17 @@ class RandomRepresentation : public Representation
40 features = Common::RandSample(count,nFeatures,0,true); 40 features = Common::RandSample(count,nFeatures,0,true);
41 } 41 }
42 42
43 - void preprocess(const Mat &src, Mat &dst) const 43 + Template preprocess(const Template &src) const
44 { 44 {
45 - representation->preprocess(src,dst); 45 + return representation->preprocess(src);
46 } 46 }
47 47
48 - float evaluate(const Mat &image, int idx) const 48 + float evaluate(const Template &src, int idx) const
49 { 49 {
50 - return representation->evaluate(image,features[idx]); 50 + return representation->evaluate(src, features[idx]);
51 } 51 }
52 52
53 - Mat evaluate(const Mat &image, const QList<int> &indices) const 53 + Mat evaluate(const Template &src, const QList<int> &indices) const
54 { 54 {
55 QList<int> newIndices; 55 QList<int> newIndices;
56 if (indices.empty()) 56 if (indices.empty())
@@ -59,7 +59,7 @@ class RandomRepresentation : public Representation @@ -59,7 +59,7 @@ class RandomRepresentation : public Representation
59 for (int i = 0; i < indices.size(); i++) 59 for (int i = 0; i < indices.size(); i++)
60 newIndices.append(features[indices[i]]); 60 newIndices.append(features[indices[i]]);
61 61
62 - return representation->evaluate(image,newIndices); 62 + return representation->evaluate(src, newIndices);
63 } 63 }
64 64
65 int numFeatures() const 65 int numFeatures() const
@@ -108,6 +108,3 @@ BR_REGISTER(Representation, RandomRepresentation) @@ -108,6 +108,3 @@ BR_REGISTER(Representation, RandomRepresentation)
108 } // namespace br 108 } // namespace br
109 109
110 #include "representation/random.moc" 110 #include "representation/random.moc"
111 -  
112 -  
113 -