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 | 131 | |
| 132 | 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 | 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 | 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 | 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 | 146 | //----------------------------- CascadeBoostParams ------------------------------------------------- | ... | ... |
openbr/core/boost.h
| ... | ... | @@ -2,7 +2,6 @@ |
| 2 | 2 | #define _BOOST_H_ |
| 3 | 3 | |
| 4 | 4 | #include "ml.h" |
| 5 | -#include <time.h> | |
| 6 | 5 | #include <openbr/openbr_plugin.h> |
| 7 | 6 | |
| 8 | 7 | #ifdef _WIN32 |
| ... | ... | @@ -17,9 +16,9 @@ namespace br |
| 17 | 16 | struct FeatureEvaluator |
| 18 | 17 | { |
| 19 | 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 | 23 | int getNumFeatures() const { return representation->numFeatures(); } |
| 25 | 24 | int getMaxCatCount() const { return representation->maxCatCount(); } |
| ... | ... | @@ -27,7 +26,8 @@ struct FeatureEvaluator |
| 27 | 26 | const cv::Mat& getCls() const { return cls; } |
| 28 | 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 | 31 | Representation *representation; |
| 32 | 32 | }; |
| 33 | 33 | ... | ... |
openbr/openbr_plugin.h
| ... | ... | @@ -882,13 +882,11 @@ public: |
| 882 | 882 | |
| 883 | 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 | 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 | 892 | virtual int numChannels() const { return 1; } |
| ... | ... | @@ -905,13 +903,13 @@ public: |
| 905 | 903 | |
| 906 | 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 | 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 | 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 | 125 | QList<Node*> classifiers; |
| 126 | 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 | 132 | CascadeBoostParams params(type, minTAR, maxFAR, trimRate, maxDepth, maxWeakCount); |
| 133 | 133 | |
| 134 | 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 | 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 | 143 | threshold = boost.getThreshold(); |
| 144 | 144 | |
| ... | ... | @@ -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 | 156 | float sum = 0; |
| 161 | 157 | for (int i = 0; i < classifiers.size(); i++) { |
| ... | ... | @@ -163,10 +159,10 @@ private: |
| 163 | 159 | |
| 164 | 160 | while (node->left) { |
| 165 | 161 | if (representation->maxCatCount() > 0) { |
| 166 | - int c = (int)representation->evaluate(m, node->featureIdx); | |
| 162 | + int c = (int)representation->evaluate(t, node->featureIdx); | |
| 167 | 163 | node = (node->subset[c >> 5] & (1 << (c & 31))) ? node->left : node->right; |
| 168 | 164 | } else { |
| 169 | - double val = representation->evaluate(m, node->featureIdx); | |
| 165 | + double val = representation->evaluate(t, node->featureIdx); | |
| 170 | 166 | node = val <= node->threshold ? node->left : node->right; |
| 171 | 167 | } |
| 172 | 168 | } |
| ... | ... | @@ -184,11 +180,9 @@ private: |
| 184 | 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 | 188 | Size windowSize(int *dx, int *dy) const | ... | ... |
openbr/plugins/classification/cascade.cpp
| 1 | 1 | #include <opencv2/imgproc/imgproc.hpp> |
| 2 | -#include <opencv2/highgui/highgui.hpp> | |
| 2 | + | |
| 3 | 3 | #include <openbr/plugins/openbr_internal.h> |
| 4 | 4 | #include <openbr/core/common.h> |
| 5 | 5 | |
| ... | ... | @@ -100,8 +100,8 @@ class CascadeClassifier : public Classifier |
| 100 | 100 | BR_PROPERTY(bool, requireAllStages, false) |
| 101 | 101 | |
| 102 | 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 | 106 | QList<int> indices; |
| 107 | 107 | int negIndex, posIndex, samplingRound; |
| ... | ... | @@ -113,18 +113,17 @@ class CascadeClassifier : public Classifier |
| 113 | 113 | negIndex = posIndex = samplingRound = 0; |
| 114 | 114 | } |
| 115 | 115 | |
| 116 | - bool getPositive(Mat &img) | |
| 116 | + bool getPositive(Template &img) | |
| 117 | 117 | { |
| 118 | 118 | if (posIndex >= posImages.size()) |
| 119 | 119 | return false; |
| 120 | - | |
| 121 | - posImages[indices[posIndex++]].copyTo(img); | |
| 120 | + img = posImages[indices[posIndex++]]; | |
| 122 | 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 | 128 | const Size size = windowSize(); |
| 130 | 129 | // Grab negative from list |
| ... | ... | @@ -136,9 +135,9 @@ class CascadeClassifier : public Classifier |
| 136 | 135 | samplingRound = samplingRound % (size.width * size.height); |
| 137 | 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 | 141 | && offset.x >= 0 && offset.y >= 0) |
| 143 | 142 | break; |
| 144 | 143 | } |
| ... | ... | @@ -150,16 +149,16 @@ class CascadeClassifier : public Classifier |
| 150 | 149 | { |
| 151 | 150 | uint64 passedNegatives = 0; |
| 152 | 151 | forever { |
| 153 | - Mat negative; | |
| 152 | + Template negative; | |
| 154 | 153 | Point offset; |
| 155 | 154 | QMutexLocker samplingLocker(&samplingMutex); |
| 156 | 155 | negative = getNegative(offset); |
| 157 | 156 | samplingLocker.unlock(); |
| 158 | 157 | |
| 159 | - Miner miner(negative, windowSize(), offset); | |
| 158 | + Miner miner(negative.m(), windowSize(), offset); | |
| 160 | 159 | forever { |
| 161 | 160 | bool newImg; |
| 162 | - Mat sample = miner.mine(&newImg); | |
| 161 | + Template sample(negative.file, miner.mine(&newImg)); | |
| 163 | 162 | if (!newImg) { |
| 164 | 163 | if (negSamples.size() >= numNegs) |
| 165 | 164 | return passedNegatives; |
| ... | ... | @@ -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 | 189 | << "\nTotal positive images:" << posImages.size() |
| 191 | 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 | 194 | stages.reserve(numStages); |
| 196 | 195 | for (int i = 0; i < numStages; i++) { |
| ... | ... | @@ -209,27 +208,17 @@ class CascadeClassifier : public Classifier |
| 209 | 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 | 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 | 219 | float stageConf = 0.0f; |
| 231 | 220 | foreach (const Classifier *stage, stages) { |
| 232 | - float result = stage->classify(image, process, &stageConf); | |
| 221 | + float result = stage->classify(src, process, &stageConf); | |
| 233 | 222 | if (confidence) |
| 234 | 223 | *confidence += stageConf; |
| 235 | 224 | if (result == 0.0f) |
| ... | ... | @@ -243,9 +232,9 @@ class CascadeClassifier : public Classifier |
| 243 | 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 | 240 | Size windowSize(int *dx = NULL, int *dy = NULL) const |
| ... | ... | @@ -273,16 +262,13 @@ class CascadeClassifier : public Classifier |
| 273 | 262 | private: |
| 274 | 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 | 267 | posIndex = 0; |
| 281 | 268 | |
| 282 | 269 | float confidence; |
| 283 | 270 | while (posSamples.size() < numPos) { |
| 284 | - Mat pos(windowSize(), CV_8UC1); | |
| 285 | - | |
| 271 | + Template pos; | |
| 286 | 272 | if (!getPositive(pos)) |
| 287 | 273 | qFatal("Cannot get another positive sample!"); |
| 288 | 274 | ... | ... |
openbr/plugins/classification/liblinear.cpp
openbr/plugins/imgproc/slidingwindow.cpp
| ... | ... | @@ -17,7 +17,6 @@ |
| 17 | 17 | #include <openbr/plugins/openbr_internal.h> |
| 18 | 18 | #include <openbr/core/opencvutils.h> |
| 19 | 19 | #include <openbr/core/qtutils.h> |
| 20 | -#include <opencv2/highgui/highgui.hpp> | |
| 21 | 20 | |
| 22 | 21 | #include <opencv2/imgproc/imgproc.hpp> |
| 23 | 22 | |
| ... | ... | @@ -35,7 +34,6 @@ namespace br |
| 35 | 34 | * \br_property int minSize The smallest sized object to detect in pixels |
| 36 | 35 | * \br_property int maxSize The largest sized object to detect in pixels. A negative value will set maxSize == image size |
| 37 | 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 | 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 | 38 | * \br_property float eps Parameter for non-maximum supression |
| 41 | 39 | */ |
| ... | ... | @@ -60,7 +58,7 @@ class SlidingWindowTransform : public MetaTransform |
| 60 | 58 | |
| 61 | 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 | 64 | void project(const Template &src, Template &dst) const |
| ... | ... | @@ -123,15 +121,18 @@ class SlidingWindowTransform : public MetaTransform |
| 123 | 121 | |
| 124 | 122 | Mat scaledImage(scaledImageSize, CV_8U, imageBuffer.data); |
| 125 | 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 | 128 | int step = factor > 2. ? 1 : 2; |
| 129 | 129 | for (int y = 0; y < processingRectSize.height; y += step) { |
| 130 | 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 | 134 | float confidence = 0; |
| 134 | - int result = classifier->classify(window, false, &confidence); | |
| 135 | + int result = classifier->classify(t, false, &confidence); | |
| 135 | 136 | |
| 136 | 137 | if (result == 1) { |
| 137 | 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 | 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 | 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 | 97 | int size = indices.empty() ? numFeatures() : indices.size(); |
| 96 | 98 | |
| 97 | 99 | Mat result(1, size, CV_32FC1); |
| 98 | 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 | 102 | return result; |
| 101 | 103 | } |
| 102 | 104 | ... | ... |
openbr/plugins/representation/mblbp.cpp
| ... | ... | @@ -39,32 +39,36 @@ class MBLBPRepresentation : public Representation |
| 39 | 39 | |
| 40 | 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 | 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 | 67 | int size = indices.empty() ? numFeatures() : indices.size(); |
| 64 | 68 | |
| 65 | 69 | Mat result(1, size, CV_32FC1); |
| 66 | 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 | 72 | return result; |
| 69 | 73 | } |
| 70 | 74 | ... | ... |
openbr/plugins/representation/npd.cpp
| ... | ... | @@ -16,23 +16,25 @@ class NPDRepresentation : public Representation |
| 16 | 16 | |
| 17 | 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 | 33 | int size = indices.empty() ? numFeatures() : indices.size(); |
| 32 | 34 | |
| 33 | 35 | Mat result(1, size, CV_32FC1); |
| 34 | 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 | 38 | return result; |
| 37 | 39 | } |
| 38 | 40 | |
| ... | ... | @@ -49,10 +51,10 @@ class NPDRepresentation : public Representation |
| 49 | 51 | struct Feature |
| 50 | 52 | { |
| 51 | 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 | 55 | float calc(const Mat &image) const; |
| 54 | 56 | |
| 55 | - int p[2]; | |
| 57 | + int p0, p1; | |
| 56 | 58 | }; |
| 57 | 59 | QList<Feature> features; |
| 58 | 60 | }; |
| ... | ... | @@ -61,9 +63,9 @@ BR_REGISTER(Representation, NPDRepresentation) |
| 61 | 63 | |
| 62 | 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 | 71 | } // namespace br | ... | ... |
openbr/plugins/representation/random.cpp
| ... | ... | @@ -28,9 +28,9 @@ class RandomRepresentation : public Representation |
| 28 | 28 | |
| 29 | 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 | 35 | const int nFeatures = representation->numFeatures(); |
| 36 | 36 | |
| ... | ... | @@ -40,17 +40,17 @@ class RandomRepresentation : public Representation |
| 40 | 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 | 55 | QList<int> newIndices; |
| 56 | 56 | if (indices.empty()) |
| ... | ... | @@ -59,7 +59,7 @@ class RandomRepresentation : public Representation |
| 59 | 59 | for (int i = 0; i < indices.size(); i++) |
| 60 | 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 | 65 | int numFeatures() const |
| ... | ... | @@ -108,6 +108,3 @@ BR_REGISTER(Representation, RandomRepresentation) |
| 108 | 108 | } // namespace br |
| 109 | 109 | |
| 110 | 110 | #include "representation/random.moc" |
| 111 | - | |
| 112 | - | |
| 113 | - | ... | ... |