diff --git a/openbr/core/boost.cpp b/openbr/core/boost.cpp index d6478c5..a8eb6d5 100644 --- a/openbr/core/boost.cpp +++ b/openbr/core/boost.cpp @@ -144,7 +144,7 @@ void FeatureEvaluator::init(Representation *_representation, int _maxSampleCount representation = _representation; int dx, dy; - Size windowSize = representation->windowSize(dx, dy); + Size windowSize = representation->windowSize(&dx, &dy); data.create((int)_maxSampleCount, Size(windowSize.width + dx, windowSize.height + dy).area(), CV_32SC1); cls.create( (int)_maxSampleCount, 1, CV_32FC1 ); } @@ -154,7 +154,7 @@ void FeatureEvaluator::setImage(const Mat &img, uchar clsLabel, int idx) cls.ptr(idx)[0] = clsLabel; int dx, dy; - Size windowSize = representation->windowSize(dx, dy); + Size windowSize = representation->windowSize(&dx, &dy); Mat integralImg(Size(windowSize.width + dx, windowSize.height + dy), data.type(), data.ptr(idx)); representation->preprocess(img, integralImg); } diff --git a/openbr/core/cascade.cpp b/openbr/core/cascade.cpp index 6db2b6e..d5b08eb 100644 --- a/openbr/core/cascade.cpp +++ b/openbr/core/cascade.cpp @@ -232,7 +232,7 @@ void _CascadeClassifier::detectMultiScale(const Mat& image, vector& object for (double factor = 1; ; factor *= scaleFactor) { int dx, dy; - Size originalWindowSize = representation->windowSize(dx, dy); + Size originalWindowSize = representation->windowSize(&dx, &dy); Size windowSize(cvRound(originalWindowSize.width*factor), cvRound(originalWindowSize.height*factor) ); Size scaledImageSize(cvRound(image.cols/factor ), cvRound(image.rows/factor)); diff --git a/openbr/openbr_plugin.h b/openbr/openbr_plugin.h index 7d14163..3a5109e 100644 --- a/openbr/openbr_plugin.h +++ b/openbr/openbr_plugin.h @@ -1407,7 +1407,7 @@ public: // and returned. virtual cv::Mat evaluate(const cv::Mat &image, const QList &indices = QList()) const = 0; - virtual cv::Size windowSize(int &dx, int &dy) const = 0; // dx and dy should indicate the change to the original window size after preprocessing + 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 virtual int numFeatures() const = 0; virtual int maxCatCount() const = 0; }; @@ -1422,11 +1422,11 @@ public: static Classifier *make(QString str, QObject *parent); /*!< \brief Make a classifier from a string. */ virtual void train(const QList &images, const QList &labels) = 0; - virtual float classify(const cv::Mat &image, float &confidence) const = 0; + virtual float classify(const cv::Mat &image, float *confidence = NULL) const = 0; // Slots for representation virtual cv::Mat preprocess(const cv::Mat &image) const = 0; - virtual cv::Size windowSize(int &dx, int &dy) const = 0; + virtual cv::Size windowSize(int *dx = NULL, int *dy = NULL) const = 0; // OpenCV compatibility virtual int numFeatures() const = 0; diff --git a/openbr/plugins/classification/boostedforest.cpp b/openbr/plugins/classification/boostedforest.cpp index 98a0fd4..6baa6e1 100644 --- a/openbr/plugins/classification/boostedforest.cpp +++ b/openbr/plugins/classification/boostedforest.cpp @@ -129,9 +129,9 @@ class BoostedForestClassifier : public Classifier } } - float classify(const Mat &image, float &confidence) const + float classify(const Mat &image, float *confidence) const { - confidence = 0; + float sum = 0; for (int i = 0; i < classifiers.size(); i++) { Node *node = classifiers[i]; @@ -144,10 +144,12 @@ class BoostedForestClassifier : public Classifier node = val <= node->threshold ? node->left : node->right; } } - confidence += node->value; + sum += node->value; } - return confidence < threshold - THRESHOLD_EPS ? 0.0f : 1.0f; + if (confidence) + *confidence = sum; + return sum < threshold - THRESHOLD_EPS ? 0.0f : 1.0f; } int numFeatures() const @@ -167,7 +169,7 @@ class BoostedForestClassifier : public Classifier return dst; } - Size windowSize(int &dx, int &dy) const + Size windowSize(int *dx, int *dy) const { return representation->windowSize(dx, dy); } diff --git a/openbr/plugins/classification/cascade.cpp b/openbr/plugins/classification/cascade.cpp index d5d73fb..59c9983 100644 --- a/openbr/plugins/classification/cascade.cpp +++ b/openbr/plugins/classification/cascade.cpp @@ -152,23 +152,18 @@ class CascadeClassifier : public Classifier } } - float classify(const Mat &image, float &confidence) const + float classify(const Mat &image, float *confidence) const { - if (stages.empty()) { - confidence = 0.0f; - return 1.0f; - } - - for (int i = 0; i < stages.size(); i++) { - float result = stages[i]->classify(image, confidence); + float stageConf = 0.0f; + foreach (const Classifier *stage, stages) { + float result = stage->classify(image, &stageConf); if (result == 0.0f) { - //confidence *= i; - return i; + if (confidence) + *confidence += stageConf; + return 0.0f; } } - - //confidence *= stages.size(); - return stages.size(); + return 1.0f; } int numFeatures() const @@ -186,7 +181,7 @@ class CascadeClassifier : public Classifier return stages.first()->preprocess(image); } - Size windowSize(int &dx, int &dy) const + Size windowSize(int *dx, int *dy) const { return stages.first()->windowSize(dx, dy); } @@ -217,14 +212,14 @@ private: { imgHandler.restart(); - float confidence = 0.0f; // not used; + float confidence = 0.0f; while (images.size() < numPos) { Mat pos(imgHandler.winSize, CV_8UC1); if (!imgHandler.getPos(pos)) qFatal("Cannot get another positive sample!"); - if (classify(pos, confidence) > 0.0f) { + if (classify(pos, &confidence) > 0.0f) { printf("POS current samples: %d\r", images.size()); images.append(pos); labels.append(1.0f); @@ -240,7 +235,7 @@ private: if (!imgHandler.getNeg(neg)) qFatal("Cannot get another negative sample!"); - if (classify(neg, confidence) > 0.0f) { + if (classify(neg, &confidence) > 0.0f) { printf("NEG current samples: %d\r", images.size() - posCount); images.append(neg); labels.append(0.0f); diff --git a/openbr/plugins/imgproc/slidingwindow.cpp b/openbr/plugins/imgproc/slidingwindow.cpp index e36b9b8..7049711 100644 --- a/openbr/plugins/imgproc/slidingwindow.cpp +++ b/openbr/plugins/imgproc/slidingwindow.cpp @@ -100,7 +100,7 @@ class SlidingWindowTransform : public MetaTransform for (double factor = 1; ; factor *= scaleFactor) { int dx, dy; - Size originalWindowSize = classifier->windowSize(dx, dy); + Size originalWindowSize = classifier->windowSize(&dx, &dy); Size windowSize(cvRound(originalWindowSize.width*factor), cvRound(originalWindowSize.height*factor) ); Size scaledImageSize(cvRound(m.cols/factor ), cvRound(m.rows/factor)); @@ -124,7 +124,7 @@ class SlidingWindowTransform : public MetaTransform Mat window = repImage(Rect(Point(x, y), Size(originalWindowSize.width + dx, originalWindowSize.height + dy))).clone(); float gypWeight; - int result = classifier->classify(window, gypWeight); + int result = classifier->classify(window, &gypWeight); if (12 - result < 4) { rects.push_back(Rect(cvRound(x*factor), cvRound(y*factor), windowSize.width, windowSize.height)); diff --git a/openbr/plugins/representation/haar.cpp b/openbr/plugins/representation/haar.cpp index 6c1d3a7..568d4ef 100644 --- a/openbr/plugins/representation/haar.cpp +++ b/openbr/plugins/representation/haar.cpp @@ -89,7 +89,14 @@ class HaarRepresentation : public Representation } int numFeatures() const { return features.size(); } - Size windowSize(int &dx, int &dy) const { dx = dy = 1; return Size(winWidth, winHeight); } + + Size windowSize(int *dx, int *dy) const + { + if (dx && dy) + *dx = *dy = 1; + return Size(winWidth, winHeight); + } + int maxCatCount() const { return 0; } struct Feature diff --git a/openbr/plugins/representation/mblbp.cpp b/openbr/plugins/representation/mblbp.cpp index 2ef19f3..4727d97 100644 --- a/openbr/plugins/representation/mblbp.cpp +++ b/openbr/plugins/representation/mblbp.cpp @@ -58,7 +58,13 @@ class MBLBPRepresentation : public Representation return result; } - Size windowSize(int &dx, int &dy) const { dx = dy = 1; return Size(winWidth, winHeight); } + Size windowSize(int *dx, int *dy) const + { + if (dx && dy) + *dx = *dy = 1; + return Size(winWidth, winHeight); + } + int numFeatures() const { return features.size(); } int maxCatCount() const { return 256; } diff --git a/openbr/plugins/representation/npd.cpp b/openbr/plugins/representation/npd.cpp new file mode 100644 index 0000000..0c1a9f9 --- /dev/null +++ b/openbr/plugins/representation/npd.cpp @@ -0,0 +1,51 @@ +#include + +using namespace cv; + +namespace br +{ + +class NPDRepresentation : public Representation +{ + Q_OBJECT + + Q_PROPERTY(int winWidth READ get_winWidth WRITE set_winWidth RESET reset_winWidth STORED false) + Q_PROPERTY(int winHeight READ get_winHeight WRITE set_winHeight RESET reset_winHeight STORED false) + BR_PROPERTY(int, winWidth, 24) + BR_PROPERTY(int, winHeight, 24) + + void init() + { + for (int p1 = 0; p1 < (winWidth * winHeight); p1++) + for (int p2 = p1; p2 < (winWidth * winHeight); p2++) + features.append(Feature(p1, p2)); + } + + float evaluate(const Mat &image, int idx) const + { + return features[idx].calc(image); + } + + Size windowSize(int *dx, int *dy) const + { + if (dx && dy) + *dx = *dy = 0; + return Size(winWidth, winHeight); + } + + struct Feature + { + Feature() {} + Feature(int p1, int p2) { p[0] = p1; p[1] = p2; } + float calc(const Mat &image) const; + + int p[2]; + }; + QList features; +}; + +BR_REGISTER(Representation, NPDRepresentation) + +} // namespace br + +#include "representation/npd.moc"