Commit 835f64e8324bfcb148202dbecaf8a29a591bfff0
Merge pull request #433 from biometrics/detection_api_update
Detection api update
Showing
11 changed files
with
108 additions
and
131 deletions
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 | 5 | ||
| @@ -100,8 +100,8 @@ class CascadeClassifier : public Classifier | @@ -100,8 +100,8 @@ class CascadeClassifier : public Classifier | ||
| 100 | BR_PROPERTY(bool, requireAllStages, false) | 100 | BR_PROPERTY(bool, requireAllStages, false) |
| 101 | 101 | ||
| 102 | QList<Classifier *> stages; | 102 | QList<Classifier *> stages; |
| 103 | - QList<Mat> posImages, negImages; | ||
| 104 | - QList<Mat> posSamples, negSamples; | 103 | + TemplateList posImages, negImages; |
| 104 | + TemplateList posSamples, negSamples; | ||
| 105 | 105 | ||
| 106 | QList<int> indices; | 106 | QList<int> indices; |
| 107 | int negIndex, posIndex, samplingRound; | 107 | int negIndex, posIndex, samplingRound; |
| @@ -113,18 +113,17 @@ class CascadeClassifier : public Classifier | @@ -113,18 +113,17 @@ class CascadeClassifier : public Classifier | ||
| 113 | negIndex = posIndex = samplingRound = 0; | 113 | negIndex = posIndex = samplingRound = 0; |
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | - bool getPositive(Mat &img) | 116 | + bool getPositive(Template &img) |
| 117 | { | 117 | { |
| 118 | if (posIndex >= posImages.size()) | 118 | if (posIndex >= posImages.size()) |
| 119 | return false; | 119 | return false; |
| 120 | - | ||
| 121 | - posImages[indices[posIndex++]].copyTo(img); | 120 | + img = posImages[indices[posIndex++]]; |
| 122 | return true; | 121 | return true; |
| 123 | } | 122 | } |
| 124 | 123 | ||
| 125 | - Mat getNegative(Point &offset) | 124 | + Template getNegative(Point &offset) |
| 126 | { | 125 | { |
| 127 | - Mat negative; | 126 | + Template negative; |
| 128 | 127 | ||
| 129 | const Size size = windowSize(); | 128 | const Size size = windowSize(); |
| 130 | // Grab negative from list | 129 | // Grab negative from list |
| @@ -136,9 +135,9 @@ class CascadeClassifier : public Classifier | @@ -136,9 +135,9 @@ class CascadeClassifier : public Classifier | ||
| 136 | samplingRound = samplingRound % (size.width * size.height); | 135 | samplingRound = samplingRound % (size.width * size.height); |
| 137 | negIndex %= count; | 136 | negIndex %= count; |
| 138 | 137 | ||
| 139 | - offset.x = qMin( (int)samplingRound % size.width, negative.cols - size.width); | ||
| 140 | - offset.y = qMin( (int)samplingRound / size.width, negative.rows - size.height); | ||
| 141 | - if (!negative.empty() && negative.type() == CV_8UC1 | 138 | + offset.x = qMin( (int)samplingRound % size.width, negative.m().cols - size.width); |
| 139 | + offset.y = qMin( (int)samplingRound / size.width, negative.m().rows - size.height); | ||
| 140 | + if (!negative.m().empty() && negative.m().type() == CV_8UC1 | ||
| 142 | && offset.x >= 0 && offset.y >= 0) | 141 | && offset.x >= 0 && offset.y >= 0) |
| 143 | break; | 142 | break; |
| 144 | } | 143 | } |
| @@ -150,16 +149,16 @@ class CascadeClassifier : public Classifier | @@ -150,16 +149,16 @@ class CascadeClassifier : public Classifier | ||
| 150 | { | 149 | { |
| 151 | uint64 passedNegatives = 0; | 150 | uint64 passedNegatives = 0; |
| 152 | forever { | 151 | forever { |
| 153 | - Mat negative; | 152 | + Template negative; |
| 154 | Point offset; | 153 | Point offset; |
| 155 | QMutexLocker samplingLocker(&samplingMutex); | 154 | QMutexLocker samplingLocker(&samplingMutex); |
| 156 | negative = getNegative(offset); | 155 | negative = getNegative(offset); |
| 157 | samplingLocker.unlock(); | 156 | samplingLocker.unlock(); |
| 158 | 157 | ||
| 159 | - Miner miner(negative, windowSize(), offset); | 158 | + Miner miner(negative.m(), windowSize(), offset); |
| 160 | forever { | 159 | forever { |
| 161 | bool newImg; | 160 | bool newImg; |
| 162 | - Mat sample = miner.mine(&newImg); | 161 | + Template sample(negative.file, miner.mine(&newImg)); |
| 163 | if (!newImg) { | 162 | if (!newImg) { |
| 164 | if (negSamples.size() >= numNegs) | 163 | if (negSamples.size() >= numNegs) |
| 165 | return passedNegatives; | 164 | return passedNegatives; |
| @@ -181,16 +180,16 @@ class CascadeClassifier : public Classifier | @@ -181,16 +180,16 @@ class CascadeClassifier : public Classifier | ||
| 181 | } | 180 | } |
| 182 | } | 181 | } |
| 183 | 182 | ||
| 184 | - void train(const QList<Mat> &images, const QList<float> &labels) | 183 | + void train(const TemplateList &data) |
| 185 | { | 184 | { |
| 186 | - for (int i = 0; i < images.size(); i++) | ||
| 187 | - labels[i] == 1 ? posImages.append(images[i]) : negImages.append(images[i]); | 185 | + foreach (const Template &t, data) |
| 186 | + t.file.get<float>("Label") == 1.0f ? posImages.append(t) : negImages.append(t); | ||
| 188 | 187 | ||
| 189 | - qDebug() << "Total images:" << images.size() | 188 | + qDebug() << "Total images:" << data.size() |
| 190 | << "\nTotal positive images:" << posImages.size() | 189 | << "\nTotal positive images:" << posImages.size() |
| 191 | << "\nTotal negative images:" << negImages.size(); | 190 | << "\nTotal negative images:" << negImages.size(); |
| 192 | 191 | ||
| 193 | - indices = Common::RandSample(posImages.size(),posImages.size(),true); | 192 | + indices = Common::RandSample(posImages.size(), posImages.size(), true); |
| 194 | 193 | ||
| 195 | stages.reserve(numStages); | 194 | stages.reserve(numStages); |
| 196 | for (int i = 0; i < numStages; i++) { | 195 | for (int i = 0; i < numStages; i++) { |
| @@ -209,27 +208,17 @@ class CascadeClassifier : public Classifier | @@ -209,27 +208,17 @@ class CascadeClassifier : public Classifier | ||
| 209 | return; | 208 | return; |
| 210 | } | 209 | } |
| 211 | 210 | ||
| 212 | - QList<float> posLabels; | ||
| 213 | - posLabels.reserve(posSamples.size()); | ||
| 214 | - for (int j=0; j<posSamples.size(); j++) | ||
| 215 | - posLabels.append(1); | ||
| 216 | - | ||
| 217 | - QList<float> negLabels; | ||
| 218 | - negLabels.reserve(negSamples.size()); | ||
| 219 | - for (int j=0; j<negSamples.size(); j++) | ||
| 220 | - negLabels.append(0); | ||
| 221 | - | ||
| 222 | - stages[i]->train(posSamples+negSamples, posLabels+negLabels); | 211 | + stages[i]->train(posSamples + negSamples); |
| 223 | 212 | ||
| 224 | qDebug() << "END>"; | 213 | qDebug() << "END>"; |
| 225 | } | 214 | } |
| 226 | } | 215 | } |
| 227 | 216 | ||
| 228 | - float classify(const Mat &image, bool process, float *confidence) const | 217 | + float classify(const Template &src, bool process, float *confidence) const |
| 229 | { | 218 | { |
| 230 | float stageConf = 0.0f; | 219 | float stageConf = 0.0f; |
| 231 | foreach (const Classifier *stage, stages) { | 220 | foreach (const Classifier *stage, stages) { |
| 232 | - float result = stage->classify(image, process, &stageConf); | 221 | + float result = stage->classify(src, process, &stageConf); |
| 233 | if (confidence) | 222 | if (confidence) |
| 234 | *confidence += stageConf; | 223 | *confidence += stageConf; |
| 235 | if (result == 0.0f) | 224 | if (result == 0.0f) |
| @@ -243,9 +232,9 @@ class CascadeClassifier : public Classifier | @@ -243,9 +232,9 @@ class CascadeClassifier : public Classifier | ||
| 243 | return stages.first()->numFeatures(); | 232 | return stages.first()->numFeatures(); |
| 244 | } | 233 | } |
| 245 | 234 | ||
| 246 | - Mat preprocess(const Mat &image) const | 235 | + Template preprocess(const Template &src) const |
| 247 | { | 236 | { |
| 248 | - return stages.first()->preprocess(image); | 237 | + return stages.first()->preprocess(src); |
| 249 | } | 238 | } |
| 250 | 239 | ||
| 251 | Size windowSize(int *dx = NULL, int *dy = NULL) const | 240 | Size windowSize(int *dx = NULL, int *dy = NULL) const |
| @@ -273,16 +262,13 @@ class CascadeClassifier : public Classifier | @@ -273,16 +262,13 @@ class CascadeClassifier : public Classifier | ||
| 273 | private: | 262 | private: |
| 274 | float getSamples() | 263 | float getSamples() |
| 275 | { | 264 | { |
| 276 | - posSamples.clear(); | ||
| 277 | - posSamples.reserve(numPos); | ||
| 278 | - negSamples.clear(); | ||
| 279 | - negSamples.reserve(numNegs); | 265 | + posSamples.clear(); posSamples.reserve(numPos); |
| 266 | + negSamples.clear(); negSamples.reserve(numNegs); | ||
| 280 | posIndex = 0; | 267 | posIndex = 0; |
| 281 | 268 | ||
| 282 | float confidence; | 269 | float confidence; |
| 283 | while (posSamples.size() < numPos) { | 270 | while (posSamples.size() < numPos) { |
| 284 | - Mat pos(windowSize(), CV_8UC1); | ||
| 285 | - | 271 | + Template pos; |
| 286 | if (!getPositive(pos)) | 272 | if (!getPositive(pos)) |
| 287 | qFatal("Cannot get another positive sample!"); | 273 | qFatal("Cannot get another positive sample!"); |
| 288 | 274 |
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, ¶m); | 141 | + //m = *train_svm(&prob, ¶m); |
| 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/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 | - |