Commit b277fd20fe92fa7f3e128e5fbc3724a150aa2149

Authored by Jordan Cheney
1 parent 447ef443

Integrated representations into the backend and reformatted into a classifier

openbr/core/boost.cpp
@@ -137,6 +137,28 @@ static CvMat* cvPreprocessIndexArray( const CvMat* idx_arr, int data_arr_size, b @@ -137,6 +137,28 @@ static CvMat* cvPreprocessIndexArray( const CvMat* idx_arr, int data_arr_size, b
137 return idx; 137 return idx;
138 } 138 }
139 139
  140 +//------------------------------------- FeatureEvaluator ---------------------------------------
  141 +
  142 +void FeatureEvaluator::init(Representation *_representation, int _maxSampleCount)
  143 +{
  144 + representation = _representation;
  145 + data.create((int)_maxSampleCount, representation->postWindowSize().area(), CV_32SC1);
  146 + cls.create( (int)_maxSampleCount, 1, CV_32FC1 );
  147 +}
  148 +
  149 +void FeatureEvaluator::setImage(const Mat &img, uchar clsLabel, int idx)
  150 +{
  151 + cls.ptr<float>(idx)[0] = clsLabel;
  152 +
  153 + Mat integralImg(representation->postWindowSize(), data.type(), data.ptr<int>(idx));
  154 + representation->preprocess(img, integralImg);
  155 +}
  156 +
  157 +void FeatureEvaluator::writeFeatures(FileStorage &fs, const Mat &featureMap) const
  158 +{
  159 + representation->write(fs, featureMap);
  160 +}
  161 +
140 //----------------------------- CascadeBoostParams ------------------------------------------------- 162 //----------------------------- CascadeBoostParams -------------------------------------------------
141 163
142 CascadeBoostParams::CascadeBoostParams() : minHitRate( 0.995F), maxFalseAlarm( 0.5F ) 164 CascadeBoostParams::CascadeBoostParams() : minHitRate( 0.995F), maxFalseAlarm( 0.5F )
openbr/core/boost.h
1 #ifndef _BOOST_H_ 1 #ifndef _BOOST_H_
2 #define _BOOST_H_ 2 #define _BOOST_H_
3 3
4 -#include "features.h"  
5 #include "ml.h" 4 #include "ml.h"
  5 +#include <openbr/openbr_plugin.h>
  6 +
  7 +#define CC_CASCADE_FILENAME "cascade.xml"
  8 +#define CC_PARAMS_FILENAME "params.xml"
  9 +
  10 +#define CC_CASCADE_PARAMS "cascadeParams"
  11 +#define CC_STAGE_TYPE "stageType"
  12 +#define CC_FEATURE_TYPE "featureType"
  13 +#define CC_HEIGHT "height"
  14 +#define CC_WIDTH "width"
  15 +
  16 +#define CC_STAGE_NUM "stageNum"
  17 +#define CC_STAGES "stages"
  18 +#define CC_STAGE_PARAMS "stageParams"
  19 +
  20 +#define CC_BOOST "BOOST"
  21 +#define CC_BOOST_TYPE "boostType"
  22 +#define CC_DISCRETE_BOOST "DAB"
  23 +#define CC_REAL_BOOST "RAB"
  24 +#define CC_LOGIT_BOOST "LB"
  25 +#define CC_GENTLE_BOOST "GAB"
  26 +#define CC_MINHITRATE "minHitRate"
  27 +#define CC_MAXFALSEALARM "maxFalseAlarm"
  28 +#define CC_TRIM_RATE "weightTrimRate"
  29 +#define CC_MAX_DEPTH "maxDeptrh"
  30 +#define CC_WEAK_COUNT "maxWeakCount"
  31 +#define CC_STAGE_THRESHOLD "stageThreshold"
  32 +#define CC_WEAK_CLASSIFIERS "weakClassifiers"
  33 +#define CC_INTERNAL_NODES "internalNodes"
  34 +#define CC_LEAF_VALUES "leafValues"
  35 +
  36 +#define CC_FEATURES "features"
  37 +#define CC_FEATURE_PARAMS "featureParams"
  38 +#define CC_MAX_CAT_COUNT "maxCatCount"
  39 +#define CC_FEATURE_SIZE "featSize"
  40 +
  41 +#define CC_LBP "LBP"
  42 +#define CC_RECT "rect"
  43 +
  44 +#ifdef _WIN32
  45 +#define TIME( arg ) (((double) clock()) / CLOCKS_PER_SEC)
  46 +#else
  47 +#define TIME( arg ) (time( arg ))
  48 +#endif
6 49
7 namespace br 50 namespace br
8 { 51 {
9 52
  53 +struct FeatureEvaluator
  54 +{
  55 + ~FeatureEvaluator() {}
  56 + void init(Representation *_representation, int _maxSampleCount);
  57 + void setImage(const cv::Mat& img, uchar clsLabel, int idx);
  58 + void writeFeatures(cv::FileStorage &fs, const cv::Mat& featureMap) const;
  59 + float operator()(int featureIdx, int sampleIdx) const { return representation->evaluate(data.row(sampleIdx), featureIdx); }
  60 +
  61 + int getNumFeatures() const { return representation->numFeatures(); }
  62 + int getMaxCatCount() const { return representation->maxCatCount(); }
  63 + int getFeatureSize() const { return 1; }
  64 + const cv::Mat& getCls() const { return cls; }
  65 + float getCls(int si) const { return cls.at<float>(si, 0); }
  66 +
  67 + cv::Mat data, cls;
  68 + Representation *representation;
  69 +};
  70 +
10 struct CascadeBoostParams : CvBoostParams 71 struct CascadeBoostParams : CvBoostParams
11 { 72 {
12 float minHitRate; 73 float minHitRate;
openbr/core/cascade.cpp deleted
1 -#include "cascade.h"  
2 -#include <stdio.h>  
3 -#include <iostream>  
4 -#include <fstream>  
5 -  
6 -using namespace std;  
7 -using namespace br;  
8 -using namespace cv;  
9 -  
10 -bool CascadeImageReader::create(const QList<Mat> &_posImages, const QList<Mat> &_negImages, Size _winSize)  
11 -{  
12 - posImages = _posImages;  
13 - negImages = _negImages;  
14 - winSize = _winSize;  
15 -  
16 - posIdx = negIdx = 0;  
17 -  
18 - src.create( 0, 0 , CV_8UC1 );  
19 - img.create( 0, 0, CV_8UC1 );  
20 - point = offset = Point( 0, 0 );  
21 - scale = 1.0F;  
22 - scaleFactor = 1.4142135623730950488016887242097F;  
23 - stepFactor = 0.5F;  
24 - round = 0;  
25 -  
26 - return true;  
27 -}  
28 -  
29 -bool CascadeImageReader::nextNeg()  
30 -{  
31 - Point _offset = Point(0,0);  
32 - size_t count = negImages.size();  
33 - for (size_t i = 0; i < count; i++) {  
34 - src = negImages[negIdx++];  
35 - if( src.empty() )  
36 - continue;  
37 - round += negIdx / count;  
38 - round = round % (winSize.width * winSize.height);  
39 - negIdx %= count;  
40 -  
41 - _offset.x = std::min( (int)round % winSize.width, src.cols - winSize.width );  
42 - _offset.y = std::min( (int)round / winSize.width, src.rows - winSize.height );  
43 - if( !src.empty() && src.type() == CV_8UC1 && _offset.x >= 0 && _offset.y >= 0 )  
44 - break;  
45 - }  
46 -  
47 - if( src.empty() )  
48 - return false; // no appropriate image  
49 - point = offset = _offset;  
50 - scale = max( ((float)winSize.width + point.x) / ((float)src.cols),  
51 - ((float)winSize.height + point.y) / ((float)src.rows) );  
52 -  
53 - Size sz( (int)(scale*src.cols + 0.5F), (int)(scale*src.rows + 0.5F) );  
54 - resize( src, img, sz );  
55 - return true;  
56 -}  
57 -  
58 -bool CascadeImageReader::getNeg( Mat& _img )  
59 -{  
60 - CV_Assert( !_img.empty() );  
61 - CV_Assert( _img.type() == CV_8UC1 );  
62 - CV_Assert( _img.cols == winSize.width );  
63 - CV_Assert( _img.rows == winSize.height );  
64 -  
65 - if( img.empty() )  
66 - if ( !nextNeg() )  
67 - return false;  
68 -  
69 - Mat mat( winSize.height, winSize.width, CV_8UC1,  
70 - (void*)(img.data + point.y * img.step + point.x * img.elemSize()), img.step );  
71 - mat.copyTo(_img);  
72 -  
73 - if( (int)( point.x + (1.0F + stepFactor ) * winSize.width ) < img.cols )  
74 - point.x += (int)(stepFactor * winSize.width);  
75 - else  
76 - {  
77 - point.x = offset.x;  
78 - if( (int)( point.y + (1.0F + stepFactor ) * winSize.height ) < img.rows )  
79 - point.y += (int)(stepFactor * winSize.height);  
80 - else  
81 - {  
82 - point.y = offset.y;  
83 - scale *= scaleFactor;  
84 - if( scale <= 1.0F )  
85 - resize( src, img, Size( (int)(scale*src.cols), (int)(scale*src.rows) ) );  
86 - else  
87 - {  
88 - if ( !nextNeg() )  
89 - return false;  
90 - }  
91 - }  
92 - }  
93 - return true;  
94 -}  
95 -  
96 -  
97 -bool CascadeImageReader::getPos(Mat &_img)  
98 -{  
99 - posImages[posIdx++].copyTo(_img);  
100 - return true;  
101 -}  
102 -  
103 -//---------------------------- CascadeClassifier --------------------------------------  
104 -  
105 -bool BrCascadeClassifier::train(const string _cascadeDirName,  
106 - const QList<Mat> &_posImages,  
107 - const QList<Mat> &_negImages,  
108 - int _numPos, int _numNeg,  
109 - int _precalcValBufSize, int _precalcIdxBufSize,  
110 - int _numStages,  
111 - Size _winSize,  
112 - const CascadeBoostParams& _stageParams)  
113 -{  
114 - // Start recording clock ticks for training time output  
115 - const clock_t begin_time = clock();  
116 -  
117 - if (_cascadeDirName.empty())  
118 - CV_Error( CV_StsBadArg, "_cascadeDirName is NULL" );  
119 -  
120 - string dirName;  
121 - if (_cascadeDirName.find_last_of("/\\") == (_cascadeDirName.length() - 1) )  
122 - dirName = _cascadeDirName;  
123 - else  
124 - dirName = _cascadeDirName + '/';  
125 -  
126 - winSize = _winSize;  
127 -  
128 - numPos = _numPos;  
129 - numNeg = _numNeg;  
130 - numStages = _numStages;  
131 - imgReader.create(_posImages, _negImages, winSize);  
132 -  
133 - Representation *representation = Representation::make("MBLBP(24,24)", NULL);  
134 -  
135 - stageParams = new CascadeBoostParams;  
136 - *stageParams = _stageParams;  
137 - featureEvaluator = new FeatureEvaluator;  
138 - featureEvaluator->init(representation, numPos + numNeg);  
139 - stageClassifiers.reserve( numStages );  
140 -  
141 - double requiredLeafFARate = pow( (double) stageParams->maxFalseAlarm, (double) numStages ) /  
142 - (double)stageParams->max_depth;  
143 - double tempLeafFARate;  
144 -  
145 - for (int i = 0; i < numStages; i++) {  
146 - cout << endl << "===== TRAINING " << i << "-stage =====" << endl;  
147 - cout << "<BEGIN" << endl;  
148 - if (!updateTrainingSet(tempLeafFARate)) {  
149 - cout << "Train dataset for temp stage can not be filled. "  
150 - "Branch training terminated." << endl;  
151 - break;  
152 - }  
153 - if (tempLeafFARate <= requiredLeafFARate) {  
154 - cout << "Required leaf false alarm rate achieved. "  
155 - "Branch training terminated." << endl;  
156 - break;  
157 - }  
158 -  
159 - CascadeBoost* tempStage = new CascadeBoost;  
160 - bool isStageTrained = tempStage->train( (FeatureEvaluator*)featureEvaluator,  
161 - curNumSamples, _precalcValBufSize, _precalcIdxBufSize,  
162 - *((CascadeBoostParams*)stageParams) );  
163 - cout << "END>" << endl;  
164 -  
165 - if (!isStageTrained)  
166 - break;  
167 -  
168 - stageClassifiers.push_back(tempStage);  
169 -  
170 - // Output training time up till now  
171 - float seconds = float( clock () - begin_time ) / CLOCKS_PER_SEC;  
172 - int days = int(seconds) / 60 / 60 / 24;  
173 - int hours = (int(seconds) / 60 / 60) % 24;  
174 - int minutes = (int(seconds) / 60) % 60;  
175 - int seconds_left = int(seconds) % 60;  
176 - cout << "Training until now has taken " << days << " days " << hours << " hours " << minutes << " minutes " << seconds_left <<" seconds." << endl;  
177 - }  
178 -  
179 - if (stageClassifiers.size() == 0) {  
180 - cout << "Cascade classifier can't be trained. Check the used training parameters." << endl;  
181 - return false;  
182 - }  
183 -  
184 - save(dirName + CC_CASCADE_FILENAME);  
185 -  
186 - return true;  
187 -}  
188 -  
189 -int BrCascadeClassifier::predict( int sampleIdx )  
190 -{  
191 - CV_DbgAssert( sampleIdx < numPos + numNeg );  
192 - for (vector< Ptr<CascadeBoost> >::iterator it = stageClassifiers.begin();  
193 - it != stageClassifiers.end(); it++ )  
194 - {  
195 - if ( (*it)->predict( sampleIdx ) == 0.f )  
196 - return 0;  
197 - }  
198 - return 1;  
199 -}  
200 -  
201 -bool BrCascadeClassifier::updateTrainingSet( double& acceptanceRatio)  
202 -{  
203 - int64 posConsumed = 0, negConsumed = 0;  
204 - imgReader.restart();  
205 -  
206 - int posCount = fillPassedSamples( 0, numPos, true, posConsumed );  
207 - if( !posCount )  
208 - return false;  
209 - cout << "POS count : consumed " << posCount << " : " << (int)posConsumed << endl;  
210 -  
211 - int proNumNeg = cvRound( ( ((double)numNeg) * ((double)posCount) ) / numPos ); // apply only a fraction of negative samples. double is required since overflow is possible  
212 - int negCount = fillPassedSamples( posCount, proNumNeg, false, negConsumed );  
213 - if ( !negCount )  
214 - return false;  
215 -  
216 - curNumSamples = posCount + negCount;  
217 - acceptanceRatio = negConsumed == 0 ? 0 : ( (double)negCount/(double)(int64)negConsumed );  
218 - cout << "NEG count : acceptanceRatio " << negCount << " : " << acceptanceRatio << endl;  
219 - return true;  
220 -}  
221 -  
222 -int BrCascadeClassifier::fillPassedSamples( int first, int count, bool isPositive, int64& consumed )  
223 -{  
224 - int getcount = 0;  
225 - Mat img(winSize, CV_8UC1);  
226 - for( int i = first; i < first + count; i++ )  
227 - {  
228 - for( ; ; )  
229 - {  
230 - bool isGetImg = isPositive ? imgReader.getPos( img ) :  
231 - imgReader.getNeg( img );  
232 - if( !isGetImg )  
233 - return getcount;  
234 - consumed++;  
235 -  
236 - featureEvaluator->setImage( img, isPositive ? 1 : 0, i );  
237 - if( predict( i ) == 1.0F )  
238 - {  
239 - getcount++;  
240 - printf("%s current samples: %d\r", isPositive ? "POS":"NEG", getcount);  
241 - break;  
242 - }  
243 - }  
244 - }  
245 - return getcount;  
246 -}  
247 -  
248 -void BrCascadeClassifier::writeParams( FileStorage &fs ) const  
249 -{  
250 - fs << CC_STAGE_TYPE << CC_BOOST;  
251 - fs << CC_FEATURE_TYPE << CC_LBP;  
252 - fs << CC_HEIGHT << winSize.height;  
253 - fs << CC_WIDTH << winSize.width;  
254 -  
255 - fs << CC_STAGE_PARAMS << "{"; stageParams->write( fs ); fs << "}";  
256 -  
257 - fs << CC_FEATURE_PARAMS << "{";  
258 - fs << CC_MAX_CAT_COUNT << featureEvaluator->getMaxCatCount();  
259 - fs << CC_FEATURE_SIZE << featureEvaluator->getFeatureSize();  
260 - fs << "}";  
261 -}  
262 -  
263 -void BrCascadeClassifier::writeFeatures( FileStorage &fs, const Mat& featureMap ) const  
264 -{  
265 - ((FeatureEvaluator*)((Ptr<FeatureEvaluator>)featureEvaluator))->writeFeatures( fs, featureMap );  
266 -}  
267 -  
268 -void BrCascadeClassifier::writeStages( FileStorage &fs, const Mat& featureMap ) const  
269 -{  
270 - char cmnt[30];  
271 - int i = 0;  
272 - fs << CC_STAGES << "[";  
273 - for( vector< Ptr<CascadeBoost> >::const_iterator it = stageClassifiers.begin();  
274 - it != stageClassifiers.end(); it++, i++ )  
275 - {  
276 - sprintf( cmnt, "stage %d", i );  
277 - cvWriteComment( fs.fs, cmnt, 0 );  
278 - fs << "{";  
279 - ((CascadeBoost*)((Ptr<CascadeBoost>)*it))->write( fs, featureMap );  
280 - fs << "}";  
281 - }  
282 - fs << "]";  
283 -}  
284 -  
285 -void BrCascadeClassifier::save(const string filename)  
286 -{  
287 - FileStorage fs( filename, FileStorage::WRITE );  
288 -  
289 - if ( !fs.isOpened() )  
290 - return;  
291 -  
292 - fs << FileStorage::getDefaultObjectName(filename) << "{";  
293 -  
294 - Mat featureMap;  
295 - getUsedFeaturesIdxMap( featureMap );  
296 - writeParams( fs );  
297 - fs << CC_STAGE_NUM << (int)stageClassifiers.size();  
298 - writeStages( fs, featureMap );  
299 - writeFeatures( fs, featureMap );  
300 -  
301 - fs << "}";  
302 -}  
303 -  
304 -void BrCascadeClassifier::getUsedFeaturesIdxMap( Mat& featureMap )  
305 -{  
306 - int varCount = featureEvaluator->getNumFeatures() * featureEvaluator->getFeatureSize();  
307 - featureMap.create( 1, varCount, CV_32SC1 );  
308 - featureMap.setTo(Scalar(-1));  
309 -  
310 - for( vector< Ptr<CascadeBoost> >::const_iterator it = stageClassifiers.begin();  
311 - it != stageClassifiers.end(); it++ )  
312 - ((CascadeBoost*)((Ptr<CascadeBoost>)(*it)))->markUsedFeaturesInMap( featureMap );  
313 -  
314 - for( int fi = 0, idx = 0; fi < varCount; fi++ )  
315 - if ( featureMap.at<int>(0, fi) >= 0 )  
316 - featureMap.ptr<int>(0)[fi] = idx++;  
317 -}  
318 -  
openbr/core/cascade.h deleted
1 -#ifndef CASCADE_H  
2 -#define CASCADE_H  
3 -  
4 -#include <openbr/openbr_plugin.h>  
5 -#include <opencv2/highgui/highgui.hpp>  
6 -#include "features.h"  
7 -#include "boost.h"  
8 -  
9 -namespace br  
10 -{  
11 -  
12 -class CascadeImageReader  
13 -{  
14 -public:  
15 - bool create( const QList<cv::Mat> &_posImages, const QList<cv::Mat> &_negImages, cv::Size _winSize );  
16 - void restart() { posIdx = 0; }  
17 - bool getNeg(cv::Mat &_img);  
18 - bool getPos(cv::Mat &_img);  
19 -  
20 - QList<cv::Mat> posImages, negImages;  
21 -  
22 - int posIdx, negIdx;  
23 -  
24 - cv::Mat src, img;  
25 - cv::Point offset, point;  
26 - float scale;  
27 - float scaleFactor;  
28 - float stepFactor;  
29 - size_t round;  
30 - cv::Size winSize;  
31 -  
32 -private:  
33 - bool nextNeg();  
34 -};  
35 -  
36 -  
37 -class BrCascadeClassifier  
38 -{  
39 -public:  
40 - bool train(const std::string _cascadeDirName,  
41 - const QList<cv::Mat> &_posImages,  
42 - const QList<cv::Mat> &_negImages,  
43 - int _numPos, int _numNeg,  
44 - int _precalcValBufSize, int _precalcIdxBufSize,  
45 - int _numStages,  
46 - cv::Size _winSize,  
47 - const CascadeBoostParams& _stageParams);  
48 -private:  
49 - int predict(int sampleIdx);  
50 - void save(const std::string cascadeDirName);  
51 - bool updateTrainingSet(double& acceptanceRatio);  
52 - int fillPassedSamples(int first, int count, bool isPositive, int64& consumed);  
53 -  
54 - void writeParams(cv::FileStorage &fs) const;  
55 - void writeStages(cv::FileStorage &fs, const cv::Mat& featureMap) const;  
56 - void writeFeatures(cv::FileStorage &fs, const cv::Mat& featureMap) const;  
57 -  
58 - void getUsedFeaturesIdxMap(cv::Mat& featureMap);  
59 -  
60 - cv::Ptr<CascadeBoostParams> stageParams;  
61 -  
62 - cv::Ptr<FeatureEvaluator> featureEvaluator;  
63 - std::vector< cv::Ptr<CascadeBoost> > stageClassifiers;  
64 - CascadeImageReader imgReader;  
65 - int numStages, curNumSamples;  
66 - int numPos, numNeg;  
67 - cv::Size winSize;  
68 -};  
69 -  
70 -} // namespace br  
71 -  
72 -#endif // CASCADE_H  
openbr/core/features.cpp deleted
1 -#include "features.h"  
2 -  
3 -using namespace cv;  
4 -using namespace br;  
5 -  
6 -//------------------------------------- FeatureEvaluator ---------------------------------------  
7 -  
8 -void FeatureEvaluator::init(Representation *_representation, int _maxSampleCount)  
9 -{  
10 - representation = _representation;  
11 - data.create((int)_maxSampleCount, representation->postWindowSize().area(), CV_32SC1);  
12 - cls.create( (int)_maxSampleCount, 1, CV_32FC1 );  
13 -}  
14 -  
15 -void FeatureEvaluator::setImage(const Mat &img, uchar clsLabel, int idx)  
16 -{  
17 - cls.ptr<float>(idx)[0] = clsLabel;  
18 -  
19 - Mat integralImg(representation->postWindowSize(), data.type(), data.ptr<int>(idx));  
20 - representation->preprocess(img, integralImg);  
21 -}  
22 -  
23 -void FeatureEvaluator::writeFeatures(FileStorage &fs, const Mat &featureMap) const  
24 -{  
25 - representation->write(fs, featureMap);  
26 -}  
openbr/core/features.h deleted
1 -#ifndef FEATURE_H  
2 -#define FEATURE_H  
3 -  
4 -#include <openbr/openbr_plugin.h>  
5 -#include "opencv2/imgproc/imgproc.hpp"  
6 -#include <iostream>  
7 -  
8 -#define CC_CASCADE_FILENAME "cascade.xml"  
9 -#define CC_PARAMS_FILENAME "params.xml"  
10 -  
11 -#define CC_CASCADE_PARAMS "cascadeParams"  
12 -#define CC_STAGE_TYPE "stageType"  
13 -#define CC_FEATURE_TYPE "featureType"  
14 -#define CC_HEIGHT "height"  
15 -#define CC_WIDTH "width"  
16 -  
17 -#define CC_STAGE_NUM "stageNum"  
18 -#define CC_STAGES "stages"  
19 -#define CC_STAGE_PARAMS "stageParams"  
20 -  
21 -#define CC_BOOST "BOOST"  
22 -#define CC_BOOST_TYPE "boostType"  
23 -#define CC_DISCRETE_BOOST "DAB"  
24 -#define CC_REAL_BOOST "RAB"  
25 -#define CC_LOGIT_BOOST "LB"  
26 -#define CC_GENTLE_BOOST "GAB"  
27 -#define CC_MINHITRATE "minHitRate"  
28 -#define CC_MAXFALSEALARM "maxFalseAlarm"  
29 -#define CC_TRIM_RATE "weightTrimRate"  
30 -#define CC_MAX_DEPTH "maxDeptrh"  
31 -#define CC_WEAK_COUNT "maxWeakCount"  
32 -#define CC_STAGE_THRESHOLD "stageThreshold"  
33 -#define CC_WEAK_CLASSIFIERS "weakClassifiers"  
34 -#define CC_INTERNAL_NODES "internalNodes"  
35 -#define CC_LEAF_VALUES "leafValues"  
36 -  
37 -#define CC_FEATURES "features"  
38 -#define CC_FEATURE_PARAMS "featureParams"  
39 -#define CC_MAX_CAT_COUNT "maxCatCount"  
40 -#define CC_FEATURE_SIZE "featSize"  
41 -  
42 -#define CC_LBP "LBP"  
43 -#define CC_RECT "rect"  
44 -  
45 -#ifdef _WIN32  
46 -#define TIME( arg ) (((double) clock()) / CLOCKS_PER_SEC)  
47 -#else  
48 -#define TIME( arg ) (time( arg ))  
49 -#endif  
50 -  
51 -namespace br  
52 -{  
53 -  
54 -class FeatureEvaluator  
55 -{  
56 -public:  
57 - ~FeatureEvaluator() {}  
58 - void init(Representation *_representation, int _maxSampleCount);  
59 - void setImage(const cv::Mat& img, uchar clsLabel, int idx);  
60 - void writeFeatures(cv::FileStorage &fs, const cv::Mat& featureMap) const;  
61 - float operator()(int featureIdx, int sampleIdx) const { return representation->evaluate(data.row(sampleIdx), featureIdx); }  
62 -  
63 - int getNumFeatures() const { return representation->numFeatures(); }  
64 - int getMaxCatCount() const { return representation->maxCatCount(); }  
65 - int getFeatureSize() const { return 1; }  
66 - const cv::Mat& getCls() const { return cls; }  
67 - float getCls(int si) const { return cls.at<float>(si, 0); }  
68 -  
69 - cv::Mat data, cls;  
70 - Representation *representation;  
71 -};  
72 -  
73 -} // namespace br  
74 -  
75 -#endif // FEATURE_H  
openbr/openbr_plugin.h
@@ -1395,11 +1395,6 @@ class BR_EXPORT Representation : public Object @@ -1395,11 +1395,6 @@ class BR_EXPORT Representation : public Object
1395 { 1395 {
1396 Q_OBJECT 1396 Q_OBJECT
1397 1397
1398 - Q_PROPERTY(int winWidth READ get_winWidth WRITE set_winWidth RESET reset_winWidth STORED false)  
1399 - Q_PROPERTY(int winHeight READ get_winHeight WRITE set_winHeight RESET reset_winHeight STORED false)  
1400 - BR_PROPERTY(int, winWidth, 24)  
1401 - BR_PROPERTY(int, winHeight, 24)  
1402 -  
1403 public: 1398 public:
1404 virtual ~Representation() {} 1399 virtual ~Representation() {}
1405 1400
openbr/plugins/classification/boostedforest.cpp
1 #include <openbr/plugins/openbr_internal.h> 1 #include <openbr/plugins/openbr_internal.h>
2 #include <openbr/core/boost.h> 2 #include <openbr/core/boost.h>
3 -#include <openbr/core/features.h>  
4 3
5 using namespace cv; 4 using namespace cv;
6 5
openbr/plugins/classification/cascade.cpp
  1 +#include <opencv2/imgproc/imgproc.hpp>
  2 +
1 #include <openbr/plugins/openbr_internal.h> 3 #include <openbr/plugins/openbr_internal.h>
2 -#include <openbr/core/features.h>  
3 #include <openbr/core/boost.h> 4 #include <openbr/core/boost.h>
4 5
5 using namespace cv; 6 using namespace cv;
@@ -9,7 +10,7 @@ namespace br @@ -9,7 +10,7 @@ namespace br
9 10
10 struct ImageHandler 11 struct ImageHandler
11 { 12 {
12 - bool create( const QList<cv::Mat> &_posImages, const QList<cv::Mat> &_negImages, cv::Size _winSize ) 13 + bool create(const QList<Mat> &_posImages, const QList<Mat> &_negImages, Size _winSize)
13 { 14 {
14 posImages = _posImages; 15 posImages = _posImages;
15 negImages = _negImages; 16 negImages = _negImages;
@@ -30,72 +31,57 @@ struct ImageHandler @@ -30,72 +31,57 @@ struct ImageHandler
30 31
31 void restart() { posIdx = 0; } 32 void restart() { posIdx = 0; }
32 33
33 - int numPos() const { return posImages.size(); }  
34 - int numNeg() const { return negImages.size(); }  
35 -  
36 - bool nextNeg() 34 + void nextNeg()
37 { 35 {
38 - Point _offset = Point(0,0);  
39 - size_t count = negImages.size();  
40 - for (size_t i = 0; i < count; i++) { 36 + int count = negImages.size();
  37 + for (int i = 0; i < count; i++) {
41 src = negImages[negIdx++]; 38 src = negImages[negIdx++];
42 - if( src.empty() )  
43 - continue; 39 +
44 round += negIdx / count; 40 round += negIdx / count;
45 round = round % (winSize.width * winSize.height); 41 round = round % (winSize.width * winSize.height);
46 negIdx %= count; 42 negIdx %= count;
47 43
48 - _offset.x = std::min( (int)round % winSize.width, src.cols - winSize.width );  
49 - _offset.y = std::min( (int)round / winSize.width, src.rows - winSize.height );  
50 - if( !src.empty() && src.type() == CV_8UC1 && _offset.x >= 0 && _offset.y >= 0 ) 44 + offset.x = qMin( (int)round % winSize.width, src.cols - winSize.width );
  45 + offset.y = qMin( (int)round / winSize.width, src.rows - winSize.height );
  46 + if (!src.empty() && src.type() == CV_8UC1 && offset.x >= 0 && offset.y >= 0)
51 break; 47 break;
52 } 48 }
53 49
54 - if( src.empty() )  
55 - return false; // no appropriate image  
56 - point = offset = _offset;  
57 - scale = max( ((float)winSize.width + point.x) / ((float)src.cols),  
58 - ((float)winSize.height + point.y) / ((float)src.rows) ); 50 + point = offset;
  51 + scale = max(((float)winSize.width + point.x) / ((float)src.cols),
  52 + ((float)winSize.height + point.y) / ((float)src.rows));
59 53
60 - Size sz( (int)(scale*src.cols + 0.5F), (int)(scale*src.rows + 0.5F) );  
61 - resize( src, img, sz );  
62 - return true; 54 + Size sz((int)(scale*src.cols + 0.5F), (int)(scale*src.rows + 0.5F));
  55 + resize(src, img, sz);
63 } 56 }
64 57
65 - bool getNeg(cv::Mat &_img) 58 + bool getNeg(Mat &_img)
66 { 59 {
67 - if( img.empty() )  
68 - if ( !nextNeg() )  
69 - return false; 60 + if (img.empty())
  61 + nextNeg();
70 62
71 - Mat mat( winSize.height, winSize.width, CV_8UC1,  
72 - (void*)(img.data + point.y * img.step + point.x * img.elemSize()), img.step );  
73 - mat.copyTo(_img); 63 + Mat m(winSize.height, winSize.width, CV_8UC1, (void*)(img.data + point.y * img.step + point.x * img.elemSize()), img.step);
  64 + m.copyTo(_img);
74 65
75 - if( (int)( point.x + (1.0F + stepFactor ) * winSize.width ) < img.cols ) 66 + if ((int)(point.x + (1.0F + stepFactor) * winSize.width) < img.cols)
76 point.x += (int)(stepFactor * winSize.width); 67 point.x += (int)(stepFactor * winSize.width);
77 - else  
78 - { 68 + else {
79 point.x = offset.x; 69 point.x = offset.x;
80 - if( (int)( point.y + (1.0F + stepFactor ) * winSize.height ) < img.rows ) 70 + if ((int)( point.y + (1.0F + stepFactor ) * winSize.height ) < img.rows)
81 point.y += (int)(stepFactor * winSize.height); 71 point.y += (int)(stepFactor * winSize.height);
82 - else  
83 - { 72 + else {
84 point.y = offset.y; 73 point.y = offset.y;
85 scale *= scaleFactor; 74 scale *= scaleFactor;
86 - if( scale <= 1.0F )  
87 - resize( src, img, Size( (int)(scale*src.cols), (int)(scale*src.rows) ) ); 75 + if (scale <= 1.0F)
  76 + resize(src, img, Size((int)(scale*src.cols), (int)(scale*src.rows)));
88 else 77 else
89 - {  
90 - if ( !nextNeg() )  
91 - return false;  
92 - } 78 + nextNeg();
93 } 79 }
94 } 80 }
95 return true; 81 return true;
96 } 82 }
97 83
98 - bool getPos(cv::Mat &_img) 84 + bool getPos(Mat &_img)
99 { 85 {
100 if (posIdx >= posImages.size()) 86 if (posIdx >= posImages.size())
101 return false; 87 return false;
@@ -104,20 +90,20 @@ struct ImageHandler @@ -104,20 +90,20 @@ struct ImageHandler
104 return true; 90 return true;
105 } 91 }
106 92
107 - QList<cv::Mat> posImages, negImages; 93 + QList<Mat> posImages, negImages;
108 94
109 int posIdx, negIdx; 95 int posIdx, negIdx;
110 96
111 - cv::Mat src, img;  
112 - cv::Point offset, point; 97 + Mat src, img;
  98 + Point offset, point;
113 float scale; 99 float scale;
114 float scaleFactor; 100 float scaleFactor;
115 float stepFactor; 101 float stepFactor;
116 size_t round; 102 size_t round;
117 - cv::Size winSize; 103 + Size winSize;
118 }; 104 };
119 105
120 -class _CascadeClassifier : public Classifier 106 +class CascadeClassifier : public Classifier
121 { 107 {
122 Q_OBJECT 108 Q_OBJECT
123 109
@@ -242,6 +228,7 @@ private: @@ -242,6 +228,7 @@ private:
242 qFatal("Cannot get another positive sample!"); 228 qFatal("Cannot get another positive sample!");
243 229
244 if (classify(pos) == 1.0f) { 230 if (classify(pos) == 1.0f) {
  231 + printf("POS current samples: %d\r", images.size());
245 images.append(pos); 232 images.append(pos);
246 labels.append(1.0f); 233 labels.append(1.0f);
247 } 234 }
@@ -257,6 +244,7 @@ private: @@ -257,6 +244,7 @@ private:
257 qFatal("Cannot get another negative sample!"); 244 qFatal("Cannot get another negative sample!");
258 245
259 if (classify(neg) == 1.0f) { 246 if (classify(neg) == 1.0f) {
  247 + printf("NEG current samples: %d\r", images.size() - posCount);
260 images.append(neg); 248 images.append(neg);
261 labels.append(0.0f); 249 labels.append(0.0f);
262 } 250 }
@@ -269,7 +257,7 @@ private: @@ -269,7 +257,7 @@ private:
269 } 257 }
270 }; 258 };
271 259
272 -BR_REGISTER(Classifier, _CascadeClassifier) 260 +BR_REGISTER(Classifier, CascadeClassifier)
273 261
274 } // namespace br 262 } // namespace br
275 263
openbr/plugins/metadata/cascade.cpp
@@ -22,7 +22,6 @@ @@ -22,7 +22,6 @@
22 #include <openbr/core/opencvutils.h> 22 #include <openbr/core/opencvutils.h>
23 #include <openbr/core/resource.h> 23 #include <openbr/core/resource.h>
24 #include <openbr/core/qtutils.h> 24 #include <openbr/core/qtutils.h>
25 -#include <openbr/core/cascade.h>  
26 25
27 using namespace cv; 26 using namespace cv;
28 27
@@ -65,34 +64,19 @@ private: @@ -65,34 +64,19 @@ private:
65 * \author Josh Klontz \cite jklontz 64 * \author Josh Klontz \cite jklontz
66 * \author David Crouse \cite dgcrouse 65 * \author David Crouse \cite dgcrouse
67 */ 66 */
68 -class CascadeTransform : public MetaTransform 67 +class CascadeTransform : public UntrainableMetaTransform
69 { 68 {
70 Q_OBJECT 69 Q_OBJECT
71 Q_PROPERTY(QString model READ get_model WRITE set_model RESET reset_model STORED false) 70 Q_PROPERTY(QString model READ get_model WRITE set_model RESET reset_model STORED false)
72 Q_PROPERTY(int minSize READ get_minSize WRITE set_minSize RESET reset_minSize STORED false) 71 Q_PROPERTY(int minSize READ get_minSize WRITE set_minSize RESET reset_minSize STORED false)
73 Q_PROPERTY(int minNeighbors READ get_minNeighbors WRITE set_minNeighbors RESET reset_minNeighbors STORED false) 72 Q_PROPERTY(int minNeighbors READ get_minNeighbors WRITE set_minNeighbors RESET reset_minNeighbors STORED false)
74 Q_PROPERTY(bool ROCMode READ get_ROCMode WRITE set_ROCMode RESET reset_ROCMode STORED false) 73 Q_PROPERTY(bool ROCMode READ get_ROCMode WRITE set_ROCMode RESET reset_ROCMode STORED false)
75 -  
76 - // Training parameters  
77 - Q_PROPERTY(QString vecFile READ get_vecFile WRITE set_vecFile RESET reset_vecFile STORED false)  
78 - Q_PROPERTY(QString negFile READ get_negFile WRITE set_negFile RESET reset_negFile STORED false)  
79 - Q_PROPERTY(int winWidth READ get_winWidth WRITE set_winWidth RESET reset_winWidth STORED false)  
80 - Q_PROPERTY(int winHeight READ get_winHeight WRITE set_winHeight RESET reset_winHeight STORED false)  
81 - Q_PROPERTY(int numPos READ get_numPos WRITE set_numPos RESET reset_numPos STORED false)  
82 - Q_PROPERTY(int numNeg READ get_numNeg WRITE set_numNeg RESET reset_numNeg STORED false)  
83 74
84 BR_PROPERTY(QString, model, "FrontalFace") 75 BR_PROPERTY(QString, model, "FrontalFace")
85 BR_PROPERTY(int, minSize, 64) 76 BR_PROPERTY(int, minSize, 64)
86 BR_PROPERTY(int, minNeighbors, 5) 77 BR_PROPERTY(int, minNeighbors, 5)
87 BR_PROPERTY(bool, ROCMode, false) 78 BR_PROPERTY(bool, ROCMode, false)
88 79
89 - BR_PROPERTY(QString, vecFile, "data.vec")  
90 - BR_PROPERTY(QString, negFile, "neg.txt")  
91 - BR_PROPERTY(int, winWidth, 24)  
92 - BR_PROPERTY(int, winHeight, 24)  
93 - BR_PROPERTY(int, numPos, 1000)  
94 - BR_PROPERTY(int, numNeg, 1000)  
95 -  
96 Resource<CascadeClassifier> cascadeResource; 80 Resource<CascadeClassifier> cascadeResource;
97 81
98 void init() 82 void init()
@@ -101,99 +85,6 @@ class CascadeTransform : public MetaTransform @@ -101,99 +85,6 @@ class CascadeTransform : public MetaTransform
101 if (model == "Ear" || model == "Eye" || model == "FrontalFace" || model == "ProfileFace") 85 if (model == "Ear" || model == "Eye" || model == "FrontalFace" || model == "ProfileFace")
102 this->trainable = false; 86 this->trainable = false;
103 } 87 }
104 -  
105 - QList<Mat> getPos()  
106 - {  
107 - FILE *file = fopen(vecFile.toStdString().c_str(), "rb");  
108 - if ( !file )  
109 - qFatal("Couldn't open the file");  
110 -  
111 - short* vec = 0;  
112 - int count, vecSize, last, base;  
113 -  
114 - short tmp = 0;  
115 - if( fread( &count, sizeof( count ), 1, file ) != 1 ||  
116 - fread( &vecSize, sizeof( vecSize ), 1, file ) != 1 ||  
117 - fread( &tmp, sizeof( tmp ), 1, file ) != 1 ||  
118 - fread( &tmp, sizeof( tmp ), 1, file ) != 1 )  
119 - CV_Error_( CV_StsParseError, ("wrong file format for %s\n", qPrintable(vecFile)) );  
120 - base = sizeof( count ) + sizeof( vecSize ) + 2*sizeof( tmp );  
121 -  
122 - last = 0;  
123 - vec = (short*) cvAlloc( sizeof( *vec ) * vecSize );  
124 - CV_Assert( vec );  
125 -  
126 - QList<Mat> posImages;  
127 - for (int i = 0; i < 35770; i++) {  
128 - Mat pos(winHeight, winWidth, CV_8UC1);  
129 -  
130 - CV_Assert( pos.rows * pos.cols == vecSize );  
131 - uchar tmp = 0;  
132 - size_t elements_read = fread( &tmp, sizeof( tmp ), 1, file );  
133 - if( elements_read != 1 )  
134 - CV_Error( CV_StsBadArg, "Can not get new positive sample. The most possible reason is "  
135 - "insufficient count of samples in given vec-file.\n");  
136 - elements_read = fread( vec, sizeof( vec[0] ), vecSize, file );  
137 - if( elements_read != (size_t)(vecSize) )  
138 - CV_Error( CV_StsBadArg, "Can not get new positive sample. Seems that vec-file has incorrect structure.\n");  
139 -  
140 - if( feof( file ) || last++ >= count )  
141 - CV_Error( CV_StsBadArg, "Can not get new positive sample. vec-file is over.\n");  
142 -  
143 - for( int r = 0; r < pos.rows; r++ )  
144 - for( int c = 0; c < pos.cols; c++ )  
145 - pos.ptr(r)[c] = (uchar)vec[r * pos.cols + c];  
146 - posImages.append(pos);  
147 - }  
148 - return posImages;  
149 - }  
150 -  
151 - QList<Mat> getNeg()  
152 - {  
153 - QList<Mat> negs;  
154 -  
155 - std::string dirname, str;  
156 - std::ifstream file(negFile.toStdString().c_str());  
157 -  
158 - size_t pos = negFile.toStdString().rfind('\\');  
159 - char dlmrt = '\\';  
160 - if (pos == string::npos)  
161 - {  
162 - pos = negFile.toStdString().rfind('/');  
163 - dlmrt = '/';  
164 - }  
165 - dirname = pos == string::npos ? "" : negFile.toStdString().substr(0, pos) + dlmrt;  
166 - while( !file.eof() )  
167 - {  
168 - std::getline(file, str);  
169 - if (str.empty()) break;  
170 - if (str.at(0) == '#' ) continue;  
171 - negs.append(imread(dirname + str, CV_LOAD_IMAGE_GRAYSCALE));  
172 - }  
173 - file.close();  
174 -  
175 - return negs;  
176 - }  
177 -  
178 - // Train transform  
179 - void train(const TemplateList& data)  
180 - {  
181 - (void)data;  
182 -  
183 - BrCascadeClassifier classifier;  
184 -  
185 - QList<Mat> posImages = getPos();  
186 - QList<Mat> negImages = getNeg();  
187 -  
188 - CascadeBoostParams stageParams(CvBoost::GENTLE, 0.999, 0.5, 0.95, 1, 200);  
189 -  
190 - QString cascadeDir = Globals->sdkPath + "/share/openbr/models/openbrcascades/" + model;  
191 - classifier.train(cascadeDir.toStdString(),  
192 - posImages, negImages,  
193 - numPos, numNeg, 1024, 1024, 12,  
194 - Size(winWidth, winHeight),  
195 - stageParams);  
196 - }  
197 88
198 void project(const Template &src, Template &dst) const 89 void project(const Template &src, Template &dst) const
199 { 90 {
openbr/plugins/representation/mblbp.cpp
@@ -22,6 +22,11 @@ class MBLBPRepresentation : public Representation @@ -22,6 +22,11 @@ class MBLBPRepresentation : public Representation
22 { 22 {
23 Q_OBJECT 23 Q_OBJECT
24 24
  25 + Q_PROPERTY(int winWidth READ get_winWidth WRITE set_winWidth RESET reset_winWidth STORED false)
  26 + Q_PROPERTY(int winHeight READ get_winHeight WRITE set_winHeight RESET reset_winHeight STORED false)
  27 + BR_PROPERTY(int, winWidth, 24)
  28 + BR_PROPERTY(int, winHeight, 24)
  29 +
25 void init() 30 void init()
26 { 31 {
27 int offset = winWidth + 1; 32 int offset = winWidth + 1;
@@ -45,9 +50,11 @@ class MBLBPRepresentation : public Representation @@ -45,9 +50,11 @@ class MBLBPRepresentation : public Representation
45 50
46 Mat evaluate(const Mat &image, const QList<int> &indices) const 51 Mat evaluate(const Mat &image, const QList<int> &indices) const
47 { 52 {
48 - Mat result(1, indices.size(), CV_32FC1);  
49 - for (int i = 0; i < indices.size(); i++)  
50 - result.at<float>(i) = (float)features[indices[i]].calc(image); 53 + int size = indices.empty() ? numFeatures() : indices.size();
  54 +
  55 + Mat result(1, size, CV_32FC1);
  56 + for (int i = 0; i < size; i++)
  57 + result.at<float>(i) = evaluate(image, indices.empty() ? i : indices[i]);
51 return result; 58 return result;
52 } 59 }
53 60