Commit 6fcc63c6bddf62527d2ae28660e97b7208343047

Authored by Jordan Cheney
1 parent dfea239c

Integrating OpenCV frontend

openbr/openbr_plugin.h
@@ -1411,9 +1411,6 @@ public: @@ -1411,9 +1411,6 @@ public:
1411 virtual cv::Size postWindowSize() const = 0; // window size after preprocessing 1411 virtual cv::Size postWindowSize() const = 0; // window size after preprocessing
1412 virtual int numFeatures() const = 0; 1412 virtual int numFeatures() const = 0;
1413 virtual int maxCatCount() const = 0; 1413 virtual int maxCatCount() const = 0;
1414 -  
1415 - // Temporary for OpenCV compatibility  
1416 - virtual void write( cv::FileStorage &fs, const cv::Mat &featureMap ) { (void)fs; (void)featureMap; }  
1417 }; 1414 };
1418 1415
1419 class BR_EXPORT Classifier : public Object 1416 class BR_EXPORT Classifier : public Object
openbr/plugins/classification/boostedforest.cpp
@@ -23,7 +23,6 @@ static void buildTreeRecursive(Node *node, const CvDTreeNode *cv_node, int maxCa @@ -23,7 +23,6 @@ static void buildTreeRecursive(Node *node, const CvDTreeNode *cv_node, int maxCa
23 { 23 {
24 if (!cv_node->left) { 24 if (!cv_node->left) {
25 node->value = cv_node->value; 25 node->value = cv_node->value;
26 -  
27 node->left = node->right = NULL; 26 node->left = node->right = NULL;
28 } else { 27 } else {
29 if (maxCatCount > 0) 28 if (maxCatCount > 0)
@@ -40,6 +39,29 @@ static void buildTreeRecursive(Node *node, const CvDTreeNode *cv_node, int maxCa @@ -40,6 +39,29 @@ static void buildTreeRecursive(Node *node, const CvDTreeNode *cv_node, int maxCa
40 } 39 }
41 } 40 }
42 41
  42 +static void readRecursive(const FileNode &fn, Node *node, int maxCatCount)
  43 +{
  44 + bool hasChildren = (int)fn["hasChildren"];
  45 + if (!hasChildren) {
  46 + node->value = (float)fn["value"];
  47 + node->left = node->right = NULL;
  48 + } else {
  49 + if (maxCatCount > 0) {
  50 + FileNode subset_fn = fn["subset"];
  51 + for (FileNodeIterator subset_it = subset_fn.begin(); subset_it != subset_fn.end(); ++subset_it)
  52 + node->subset.append((int)*subset_it);
  53 + } else {
  54 + node->threshold = (float)fn["threshold"];
  55 + }
  56 +
  57 + node->featureIdx = (int)fn["featureIdx"];
  58 +
  59 + node->left = new Node; node->right = new Node;
  60 + readRecursive(fn["left"], node->left, maxCatCount);
  61 + readRecursive(fn["right"], node->right, maxCatCount);
  62 + }
  63 +}
  64 +
43 static void writeRecursive(FileStorage &fs, const Node *node, int maxCatCount) 65 static void writeRecursive(FileStorage &fs, const Node *node, int maxCatCount)
44 { 66 {
45 bool hasChildren = node->left ? true : false; 67 bool hasChildren = node->left ? true : false;
@@ -119,16 +141,17 @@ class BoostedForestClassifier : public Classifier @@ -119,16 +141,17 @@ class BoostedForestClassifier : public Classifier
119 while (node->left) { 141 while (node->left) {
120 if (representation->maxCatCount() > 1) { 142 if (representation->maxCatCount() > 1) {
121 int c = (int)representation->evaluate(image, node->featureIdx); 143 int c = (int)representation->evaluate(image, node->featureIdx);
122 - node = (2*((node->subset[c >> 5] & (1 << (c & 31))) == 0) - 1) < 0 ? node->left : node->right; 144 + node = (node->subset[c >> 5] & (1 << (c & 31))) ? node->left : node->right;
123 } else { 145 } else {
124 double val = representation->evaluate(image, node->featureIdx); 146 double val = representation->evaluate(image, node->featureIdx);
125 node = val <= node->threshold ? node->left : node->right; 147 node = val <= node->threshold ? node->left : node->right;
126 } 148 }
127 } 149 }
  150 + qDebug("value: %f", node->value);
128 sum += node->value; 151 sum += node->value;
129 } 152 }
130 153
131 - return sum < threshold - THRESHOLD_EPS ? 0.0f : 1.0f; 154 + return sum < threshold - THRESHOLD_EPS ? -std::abs(sum) : std::abs(sum);
132 } 155 }
133 156
134 int numFeatures() const 157 int numFeatures() const
@@ -146,6 +169,17 @@ class BoostedForestClassifier : public Classifier @@ -146,6 +169,17 @@ class BoostedForestClassifier : public Classifier
146 return representation->preWindowSize(); 169 return representation->preWindowSize();
147 } 170 }
148 171
  172 + void read(const FileNode &node)
  173 + {
  174 + threshold = (float)node["stageThreshold"];
  175 + FileNode weaks_fn = node["weakClassifiers"];
  176 + for (FileNodeIterator weaks_it = weaks_fn.begin(); weaks_it != weaks_fn.end(); ++weaks_it) {
  177 + Node *root = new Node;
  178 + readRecursive(*weaks_it, root, representation->maxCatCount());
  179 + classifiers.append(root);
  180 + }
  181 + }
  182 +
149 void write(FileStorage &fs) const 183 void write(FileStorage &fs) const
150 { 184 {
151 fs << "stageThreshold" << threshold; 185 fs << "stageThreshold" << threshold;
openbr/plugins/classification/cascade.cpp
@@ -154,10 +154,16 @@ class CascadeClassifier : public Classifier @@ -154,10 +154,16 @@ class CascadeClassifier : public Classifier
154 154
155 float classify(const Mat &image) const 155 float classify(const Mat &image) const
156 { 156 {
157 - foreach (const Classifier *stage, stages)  
158 - if (stage->classify(image) == 0.0f)  
159 - return 0.0f;  
160 - return 1.0f; 157 + if (stages.empty())
  158 + return 1.0f;
  159 +
  160 + float val = 0.0f;
  161 + for (int i = 0; i < stages.size(); i++) {
  162 + val = stages[i]->classify(image);
  163 + if (val < 0.0f)
  164 + return stages.size() - i < 4 ? i * val : 0.0f;
  165 + }
  166 + return stages.size() * val;
161 } 167 }
162 168
163 int numFeatures() const 169 int numFeatures() const
@@ -175,6 +181,16 @@ class CascadeClassifier : public Classifier @@ -175,6 +181,16 @@ class CascadeClassifier : public Classifier
175 return stages.first()->windowSize(); 181 return stages.first()->windowSize();
176 } 182 }
177 183
  184 + void read(const FileNode &node)
  185 + {
  186 + FileNode stages_fn = node["stages"];
  187 + for (FileNodeIterator stages_it = stages_fn.begin(); stages_it != stages_fn.end(); ++stages_it) {
  188 + Classifier *nextStage = Classifier::make(stageDescription, NULL);
  189 + nextStage->read(*stages_it);
  190 + stages.append(nextStage);
  191 + }
  192 + }
  193 +
178 void write(FileStorage &fs) const 194 void write(FileStorage &fs) const
179 { 195 {
180 fs << "stages" << "["; 196 fs << "stages" << "[";
@@ -196,7 +212,7 @@ private: @@ -196,7 +212,7 @@ private:
196 if (!imgHandler.getPos(pos)) 212 if (!imgHandler.getPos(pos))
197 qFatal("Cannot get another positive sample!"); 213 qFatal("Cannot get another positive sample!");
198 214
199 - if (classify(pos) == 1.0f) { 215 + if (classify(pos) > 0.0f) {
200 printf("POS current samples: %d\r", images.size()); 216 printf("POS current samples: %d\r", images.size());
201 images.append(pos); 217 images.append(pos);
202 labels.append(1.0f); 218 labels.append(1.0f);
@@ -212,7 +228,7 @@ private: @@ -212,7 +228,7 @@ private:
212 if (!imgHandler.getNeg(neg)) 228 if (!imgHandler.getNeg(neg))
213 qFatal("Cannot get another negative sample!"); 229 qFatal("Cannot get another negative sample!");
214 230
215 - if (classify(neg) == 1.0f) { 231 + if (classify(neg) > 0.0f) {
216 printf("NEG current samples: %d\r", images.size() - posCount); 232 printf("NEG current samples: %d\r", images.size() - posCount);
217 images.append(neg); 233 images.append(neg);
218 labels.append(0.0f); 234 labels.append(0.0f);
openbr/plugins/imgproc/slidingwindow.cpp
@@ -19,8 +19,10 @@ @@ -19,8 +19,10 @@
19 #include <openbr/plugins/openbr_internal.h> 19 #include <openbr/plugins/openbr_internal.h>
20 #include <openbr/core/opencvutils.h> 20 #include <openbr/core/opencvutils.h>
21 #include <openbr/core/qtutils.h> 21 #include <openbr/core/qtutils.h>
  22 +#include <openbr/core/cascade.h>
22 23
23 #include <opencv2/highgui/highgui.hpp> 24 #include <opencv2/highgui/highgui.hpp>
  25 +#include <opencv2/imgproc/imgproc.hpp>
24 26
25 using namespace cv; 27 using namespace cv;
26 28
@@ -38,8 +40,20 @@ class SlidingWindowTransform : public Transform @@ -38,8 +40,20 @@ class SlidingWindowTransform : public Transform
38 Q_OBJECT 40 Q_OBJECT
39 41
40 Q_PROPERTY(br::Classifier *classifier READ get_classifier WRITE set_classifier RESET reset_classifier STORED false) 42 Q_PROPERTY(br::Classifier *classifier READ get_classifier WRITE set_classifier RESET reset_classifier STORED false)
  43 + Q_PROPERTY(int minSize READ get_minSize WRITE set_minSize RESET reset_minSize STORED false)
  44 + Q_PROPERTY(int maxSize READ get_maxSize WRITE set_maxSize RESET reset_maxSize STORED false)
  45 + Q_PROPERTY(float scaleFactor READ get_scaleFactor WRITE set_scaleFactor RESET reset_scaleFactor STORED false)
  46 + Q_PROPERTY(int minNeighbors READ get_minNeighbors WRITE set_minNeighbors RESET reset_minNeighbors STORED false)
  47 + Q_PROPERTY(float eps READ get_eps WRITE set_eps RESET reset_eps STORED false)
  48 +
41 Q_PROPERTY(QString cascadeDir READ get_cascadeDir WRITE set_cascadeDir RESET reset_cascadeDir STORED false) 49 Q_PROPERTY(QString cascadeDir READ get_cascadeDir WRITE set_cascadeDir RESET reset_cascadeDir STORED false)
42 BR_PROPERTY(br::Classifier *, classifier, NULL) 50 BR_PROPERTY(br::Classifier *, classifier, NULL)
  51 + BR_PROPERTY(int, minSize, 20)
  52 + BR_PROPERTY(int, maxSize, -1)
  53 + BR_PROPERTY(float, scaleFactor, 1.2)
  54 + BR_PROPERTY(int, minNeighbors, 5)
  55 + BR_PROPERTY(float, eps, 0.2)
  56 +
43 BR_PROPERTY(QString, cascadeDir, "") 57 BR_PROPERTY(QString, cascadeDir, "")
44 58
45 void train(const TemplateList &data) 59 void train(const TemplateList &data)
@@ -49,12 +63,104 @@ class SlidingWindowTransform : public Transform @@ -49,12 +63,104 @@ class SlidingWindowTransform : public Transform
49 63
50 void project(const Template &src, Template &dst) const 64 void project(const Template &src, Template &dst) const
51 { 65 {
52 - (void)src; (void)dst; 66 + TemplateList temp;
  67 + project(TemplateList() << src, temp);
  68 + if (!temp.isEmpty()) dst = temp.first();
53 } 69 }
54 70
  71 + void project(const TemplateList &src, TemplateList &dst) const
  72 + {
  73 + foreach (const Template &t, src) {
  74 + const bool enrollAll = t.file.getBool("enrollAll");
  75 +
  76 + // Mirror the behavior of ExpandTransform in the special case
  77 + // of an empty template.
  78 + if (t.empty() && !enrollAll) {
  79 + dst.append(t);
  80 + continue;
  81 + }
  82 +
  83 + for (int i = 0; i < t.size(); i++) {
  84 + Mat image;
  85 + OpenCVUtils::cvtUChar(t[i], image);
  86 +
  87 + std::vector<Rect> rects;
  88 + std::vector<int> rejectLevels;
  89 + std::vector<double> levelWeights;
  90 +
  91 + Size minObjectSize(minSize, minSize);
  92 + Size maxObjectSize(maxSize, maxSize);
  93 + if (maxObjectSize.height <= 0 || maxObjectSize.width <= 0)
  94 + maxObjectSize = image.size();
  95 +
  96 + Mat imageBuffer(image.rows + 1, image.cols + 1, CV_8U);
  97 +
  98 + for (double factor = 1; ; factor *= scaleFactor) {
  99 + Size originalWindowSize = classifier->windowSize();
  100 +
  101 + Size windowSize(cvRound(originalWindowSize.width*factor), cvRound(originalWindowSize.height*factor) );
  102 + Size scaledImageSize(cvRound(image.cols/factor ), cvRound(image.rows/factor));
  103 + Size processingRectSize(scaledImageSize.width - originalWindowSize.width, scaledImageSize.height - originalWindowSize.height);
  104 +
  105 + if (processingRectSize.width <= 0 || processingRectSize.height <= 0)
  106 + break;
  107 + if (windowSize.width > maxObjectSize.width || windowSize.height > maxObjectSize.height)
  108 + break;
  109 + if (windowSize.width < minObjectSize.width || windowSize.height < minObjectSize.height)
  110 + continue;
  111 +
  112 + Mat scaledImage(scaledImageSize, CV_8U, imageBuffer.data);
  113 + resize(image, scaledImage, scaledImageSize, 0, 0, CV_INTER_LINEAR);
  114 +
  115 + int yStep = factor > 2. ? 1 : 2;
  116 + for (int y = 0; y < processingRectSize.height; y += yStep) {
  117 + for (int x = 0; x < processingRectSize.width; x += yStep) {
  118 + Mat window = scaledImage(Rect(Point(x, y), classifier->windowSize())).clone();
  119 +
  120 + float result = classifier->classify(window);
  121 + qDebug("result: %f", result);
  122 + if (result > 0) {
  123 + rects.push_back(Rect(cvRound(x*factor), cvRound(y*factor), windowSize.width, windowSize.height));
  124 + rejectLevels.push_back(1);
  125 + levelWeights.push_back(result);
  126 + }
  127 + if (result == 0)
  128 + x = yStep;
  129 + }
  130 + }
  131 + }
  132 +
  133 + groupRectangles(rects, rejectLevels, levelWeights, minNeighbors, eps);
  134 +
  135 + if (!enrollAll && rects.empty())
  136 + rects.push_back(Rect(0, 0, image.cols, image.rows));
  137 +
  138 + for (size_t j = 0; j < rects.size(); j++) {
  139 + Template u(t.file, image);
  140 + if (rejectLevels.size() > j)
  141 + u.file.set("Confidence", rejectLevels[j]*levelWeights[j]);
  142 + else
  143 + u.file.set("Confidence", 1);
  144 + const QRectF rect = OpenCVUtils::fromRect(rects[j]);
  145 + u.file.appendRect(rect);
  146 + u.file.set("Face", rect);
  147 + dst.append(u);
  148 + }
  149 + }
  150 + }
  151 + }
  152 +
55 void load(QDataStream &stream) 153 void load(QDataStream &stream)
56 { 154 {
57 (void) stream; 155 (void) stream;
  156 +
  157 + QString filename = Globals->sdkPath + "/share/openbr/models/openbrcascades/" + cascadeDir + "/cascade.xml";
  158 + FileStorage fs(filename.toStdString(), FileStorage::READ);
  159 + if (!fs.isOpened())
  160 + return;
  161 +
  162 + classifier->read(fs.getFirstTopLevelNode());
  163 +
58 return; 164 return;
59 } 165 }
60 166
@@ -62,17 +168,17 @@ class SlidingWindowTransform : public Transform @@ -62,17 +168,17 @@ class SlidingWindowTransform : public Transform
62 { 168 {
63 (void) stream; 169 (void) stream;
64 170
65 - QString path = Globals->sdkPath + "/share/openbr/models/openbrcascades/" + cascadeDir;  
66 - QtUtils::touchDir(QDir(path)); 171 + QString path = Globals->sdkPath + "/share/openbr/models/openbrcascades/" + cascadeDir;
  172 + QtUtils::touchDir(QDir(path));
67 173
68 - QString filename = path + "/cascade.xml"; 174 + QString filename = path + "/cascade.xml";
69 FileStorage fs(filename.toStdString(), FileStorage::WRITE); 175 FileStorage fs(filename.toStdString(), FileStorage::WRITE);
70 176
71 if (!fs.isOpened()) { 177 if (!fs.isOpened()) {
72 - qWarning("Unable to open file: %s", qPrintable(filename)); 178 + qWarning("Unable to open file: %s", qPrintable(filename));
73 return; 179 return;
74 - }  
75 - 180 + }
  181 +
76 fs << FileStorage::getDefaultObjectName(filename.toStdString()) << "{"; 182 fs << FileStorage::getDefaultObjectName(filename.toStdString()) << "{";
77 183
78 classifier->write(fs); 184 classifier->write(fs);
openbr/plugins/representation/mblbp.cpp
@@ -58,7 +58,6 @@ class MBLBPRepresentation : public Representation @@ -58,7 +58,6 @@ class MBLBPRepresentation : public Representation
58 return result; 58 return result;
59 } 59 }
60 60
61 - void write(FileStorage &fs, const Mat &featureMap);  
62 int numFeatures() const { return features.size(); } 61 int numFeatures() const { return features.size(); }
63 Size preWindowSize() const { return Size(winWidth, winHeight); } 62 Size preWindowSize() const { return Size(winWidth, winHeight); }
64 Size postWindowSize() const { return Size(winWidth + 1, winHeight + 1); } 63 Size postWindowSize() const { return Size(winWidth + 1, winHeight + 1); }
@@ -69,7 +68,6 @@ class MBLBPRepresentation : public Representation @@ -69,7 +68,6 @@ class MBLBPRepresentation : public Representation
69 Feature() { rect = Rect(0, 0, 0, 0); } 68 Feature() { rect = Rect(0, 0, 0, 0); }
70 Feature( int offset, int x, int y, int _block_w, int _block_h ); 69 Feature( int offset, int x, int y, int _block_w, int _block_h );
71 uchar calc(const Mat &img) const; 70 uchar calc(const Mat &img) const;
72 - void write( FileStorage &fs ) const { fs << "rect" << "[:" << rect.x << rect.y << rect.width << rect.height << "]"; }  
73 71
74 Rect rect; 72 Rect rect;
75 int p[16]; 73 int p[16];
@@ -79,20 +77,6 @@ class MBLBPRepresentation : public Representation @@ -79,20 +77,6 @@ class MBLBPRepresentation : public Representation
79 77
80 BR_REGISTER(Representation, MBLBPRepresentation) 78 BR_REGISTER(Representation, MBLBPRepresentation)
81 79
82 -void MBLBPRepresentation::write(FileStorage &fs, const Mat &featureMap)  
83 -{  
84 - fs << "features" << "[";  
85 - const Mat_<int>& featureMap_ = (const Mat_<int>&)featureMap;  
86 - for ( int fi = 0; fi < featureMap.cols; fi++ )  
87 - if ( featureMap_(0, fi) >= 0 )  
88 - {  
89 - fs << "{";  
90 - features[fi].write( fs );  
91 - fs << "}";  
92 - }  
93 - fs << "]";  
94 -}  
95 -  
96 MBLBPRepresentation::Feature::Feature( int offset, int x, int y, int _blockWidth, int _blockHeight ) 80 MBLBPRepresentation::Feature::Feature( int offset, int x, int y, int _blockWidth, int _blockHeight )
97 { 81 {
98 Rect tr = rect = cvRect(x, y, _blockWidth, _blockHeight); 82 Rect tr = rect = cvRect(x, y, _blockWidth, _blockHeight);