6 #define CC_CASCADE_PARAMS "cascadeParams"
7 #define CC_STAGE_TYPE "stageType"
8 #define CC_FEATURE_TYPE "featureType"
9 #define CC_HEIGHT "height"
10 #define CC_WIDTH "width"
12 #define CC_STAGE_NUM "stageNum"
13 #define CC_STAGES "stages"
14 #define CC_STAGE_PARAMS "stageParams"
16 #define CC_BOOST "BOOST"
17 #define CC_MAX_DEPTH "maxDepth"
18 #define CC_WEAK_COUNT "maxWeakCount"
19 #define CC_STAGE_THRESHOLD "stageThreshold"
20 #define CC_WEAK_CLASSIFIERS "weakClassifiers"
21 #define CC_INTERNAL_NODES "internalNodes"
22 #define CC_LEAF_VALUES "leafValues"
24 #define CC_FEATURES "features"
25 #define CC_FEATURE_PARAMS "featureParams"
26 #define CC_MAX_CAT_COUNT "maxCatCount"
28 #define CC_HAAR "HAAR"
29 #define CC_RECTS "rects"
30 #define CC_TILTED "tilted"
33 #define CC_RECT "rect"
37 #define CV_SUM_PTRS( p0, p1, p2, p3, sum, rect, step ) \
39 (p0) = sum + (rect).x + (step) * (rect).y, \
41 (p1) = sum + (rect).x + (rect).width + (step) * (rect).y, \
43 (p2) = sum + (rect).x + (step) * ((rect).y + (rect).height), \
44 /* (x + w, y + h) */ \
45 (p3) = sum + (rect).x + (rect).width + (step) * ((rect).y + (rect).height)
47 #define CV_TILTED_PTRS( p0, p1, p2, p3, tilted, rect, step ) \
49 (p0) = tilted + (rect).x + (step) * (rect).y, \
50 /* (x - h, y + h) */ \
51 (p1) = tilted + (rect).x - (rect).height + (step) * ((rect).y + (rect).height), \
52 /* (x + w, y + w) */ \
53 (p2) = tilted + (rect).x + (rect).width + (step) * ((rect).y + (rect).width), \
54 /* (x + w - h, y + w + h) */ \
55 (p3) = tilted + (rect).x + (rect).width - (rect).height \
56 + (step) * ((rect).y + (rect).width + (rect).height)
58 #define CALC_SUM_(p0, p1, p2, p3, offset) \
59 ((p0)[offset] - (p1)[offset] - (p2)[offset] + (p3)[offset])
61 #define CALC_SUM(rect,offset) CALC_SUM_((rect)[0], (rect)[1], (rect)[2], (rect)[3], offset)
64 //---------------------------------------------- HaarEvaluator ---------------------------------------
65 class HaarEvaluator : public FeatureEvaluator
72 float calc( int offset ) const;
73 void updatePtrs( const Mat& sum );
74 bool read( const FileNode& node );
78 enum { RECT_NUM = 3 };
86 const int* p[RECT_NUM][4];
90 virtual ~HaarEvaluator();
92 virtual bool read( const FileNode& node );
93 virtual Ptr<FeatureEvaluator> clone() const;
94 virtual int getFeatureType() const { return FeatureEvaluator::HAAR; }
96 virtual bool setImage(const Mat&, Size origWinSize);
97 virtual bool setWindow(Point pt);
99 double operator()(int featureIdx) const
100 { return featuresPtr[featureIdx].calc(offset) * varianceNormFactor; }
101 virtual double calcOrd(int featureIdx) const
102 { return (*this)(featureIdx); }
106 Ptr<vector<Feature> > features;
107 Feature* featuresPtr; // optimization
108 bool hasTiltedFeatures;
110 Mat sum0, sqsum0, tilted0;
111 Mat sum, sqsum, tilted;
118 double varianceNormFactor;
121 inline HaarEvaluator::Feature :: Feature()
124 rect[0].r = rect[1].r = rect[2].r = Rect();
125 rect[0].weight = rect[1].weight = rect[2].weight = 0;
126 p[0][0] = p[0][1] = p[0][2] = p[0][3] =
127 p[1][0] = p[1][1] = p[1][2] = p[1][3] =
128 p[2][0] = p[2][1] = p[2][2] = p[2][3] = 0;
131 inline float HaarEvaluator::Feature :: calc( int _offset ) const
133 float ret = rect[0].weight * CALC_SUM(p[0], _offset) + rect[1].weight * CALC_SUM(p[1], _offset);
135 if( rect[2].weight != 0.0f )
136 ret += rect[2].weight * CALC_SUM(p[2], _offset);
141 inline void HaarEvaluator::Feature :: updatePtrs( const Mat& _sum )
143 const int* ptr = (const int*)_sum.data;
144 size_t step = _sum.step/sizeof(ptr[0]);
147 CV_TILTED_PTRS( p[0][0], p[0][1], p[0][2], p[0][3], ptr, rect[0].r, step );
148 CV_TILTED_PTRS( p[1][0], p[1][1], p[1][2], p[1][3], ptr, rect[1].r, step );
150 CV_TILTED_PTRS( p[2][0], p[2][1], p[2][2], p[2][3], ptr, rect[2].r, step );
154 CV_SUM_PTRS( p[0][0], p[0][1], p[0][2], p[0][3], ptr, rect[0].r, step );
155 CV_SUM_PTRS( p[1][0], p[1][1], p[1][2], p[1][3], ptr, rect[1].r, step );
157 CV_SUM_PTRS( p[2][0], p[2][1], p[2][2], p[2][3], ptr, rect[2].r, step );
162 //---------------------------------------------- LBPEvaluator -------------------------------------
164 class LBPEvaluator : public FeatureEvaluator
170 Feature( int x, int y, int _block_w, int _block_h ) :
171 rect(x, y, _block_w, _block_h) {}
173 int calc( int offset ) const;
174 void updatePtrs( const Mat& sum );
175 bool read(const FileNode& node );
177 Rect rect; // weight and height for block
178 const int* p[16]; // fast
182 virtual ~LBPEvaluator();
184 virtual bool read( const FileNode& node );
185 virtual Ptr<FeatureEvaluator> clone() const;
186 virtual int getFeatureType() const { return FeatureEvaluator::LBP; }
188 virtual bool setImage(const Mat& image, Size _origWinSize);
189 virtual bool setWindow(Point pt);
191 int operator()(int featureIdx) const
192 { return featuresPtr[featureIdx].calc(offset); }
193 virtual int calcCat(int featureIdx) const
194 { return (*this)(featureIdx); }
197 Ptr<vector<Feature> > features;
198 Feature* featuresPtr; // optimization
206 inline LBPEvaluator::Feature :: Feature()
209 for( int i = 0; i < 16; i++ )
213 inline int LBPEvaluator::Feature :: calc( int _offset ) const
215 int cval = CALC_SUM_( p[5], p[6], p[9], p[10], _offset );
217 return (CALC_SUM_( p[0], p[1], p[4], p[5], _offset ) >= cval ? 128 : 0) | // 0
218 (CALC_SUM_( p[1], p[2], p[5], p[6], _offset ) >= cval ? 64 : 0) | // 1
219 (CALC_SUM_( p[2], p[3], p[6], p[7], _offset ) >= cval ? 32 : 0) | // 2
220 (CALC_SUM_( p[6], p[7], p[10], p[11], _offset ) >= cval ? 16 : 0) | // 5
221 (CALC_SUM_( p[10], p[11], p[14], p[15], _offset ) >= cval ? 8 : 0)| // 8
222 (CALC_SUM_( p[9], p[10], p[13], p[14], _offset ) >= cval ? 4 : 0)| // 7
223 (CALC_SUM_( p[8], p[9], p[12], p[13], _offset ) >= cval ? 2 : 0)| // 6
224 (CALC_SUM_( p[4], p[5], p[8], p[9], _offset ) >= cval ? 1 : 0);
227 inline void LBPEvaluator::Feature :: updatePtrs( const Mat& _sum )
229 const int* ptr = (const int*)_sum.data;
230 size_t step = _sum.step/sizeof(ptr[0]);
232 CV_SUM_PTRS( p[0], p[1], p[4], p[5], ptr, tr, step );
233 tr.x += 2*rect.width;
234 CV_SUM_PTRS( p[2], p[3], p[6], p[7], ptr, tr, step );
235 tr.y += 2*rect.height;
236 CV_SUM_PTRS( p[10], p[11], p[14], p[15], ptr, tr, step );
237 tr.x -= 2*rect.width;
238 CV_SUM_PTRS( p[8], p[9], p[12], p[13], ptr, tr, step );
241 //---------------------------------------------- HOGEvaluator -------------------------------------------
243 class HOGEvaluator : public FeatureEvaluator
249 float calc( int offset ) const;
250 void updatePtrs( const vector<Mat>& _hist, const Mat &_normSum );
251 bool read( const FileNode& node );
253 enum { CELL_NUM = 4, BIN_NUM = 9 };
256 int featComponent; //component index from 0 to 35
257 const float* pF[4]; //for feature calculation
258 const float* pN[4]; //for normalization calculation
261 virtual ~HOGEvaluator();
262 virtual bool read( const FileNode& node );
263 virtual Ptr<FeatureEvaluator> clone() const;
264 virtual int getFeatureType() const { return FeatureEvaluator::HOG; }
265 virtual bool setImage( const Mat& image, Size winSize );
266 virtual bool setWindow( Point pt );
267 double operator()(int featureIdx) const
269 return featuresPtr[featureIdx].calc(offset);
271 virtual double calcOrd( int featureIdx ) const
273 return (*this)(featureIdx);
277 virtual void integralHistogram( const Mat& srcImage, vector<Mat> &histogram, Mat &norm, int nbins ) const;
280 Ptr<vector<Feature> > features;
281 Feature* featuresPtr;
287 inline HOGEvaluator::Feature :: Feature()
289 rect[0] = rect[1] = rect[2] = rect[3] = Rect();
290 pF[0] = pF[1] = pF[2] = pF[3] = 0;
291 pN[0] = pN[1] = pN[2] = pN[3] = 0;
295 inline float HOGEvaluator::Feature :: calc( int _offset ) const
297 float res = CALC_SUM(pF, _offset);
298 float normFactor = CALC_SUM(pN, _offset);
299 res = (res > 0.001f) ? (res / ( normFactor + 0.001f) ) : 0.f;
303 inline void HOGEvaluator::Feature :: updatePtrs( const vector<Mat> &_hist, const Mat &_normSum )
305 int binIdx = featComponent % BIN_NUM;
306 int cellIdx = featComponent / BIN_NUM;
307 Rect normRect = Rect( rect[0].x, rect[0].y, 2*rect[0].width, 2*rect[0].height );
309 const float* featBuf = (const float*)_hist[binIdx].data;
310 size_t featStep = _hist[0].step / sizeof(featBuf[0]);
312 const float* normBuf = (const float*)_normSum.data;
313 size_t normStep = _normSum.step / sizeof(normBuf[0]);
315 CV_SUM_PTRS( pF[0], pF[1], pF[2], pF[3], featBuf, rect[cellIdx], featStep );
316 CV_SUM_PTRS( pN[0], pN[1], pN[2], pN[3], normBuf, normRect, normStep );
322 //---------------------------------------------- predictor functions -------------------------------------
324 template<class FEval>
325 inline int predictOrdered( CascadeClassifier& cascade, Ptr<FeatureEvaluator> &_featureEvaluator, double& sum )
327 int nstages = (int)cascade.data.stages.size();
328 int nodeOfs = 0, leafOfs = 0;
329 FEval& featureEvaluator = (FEval&)*_featureEvaluator;
330 float* cascadeLeaves = &cascade.data.leaves[0];
331 CascadeClassifier::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0];
332 CascadeClassifier::Data::DTree* cascadeWeaks = &cascade.data.classifiers[0];
333 CascadeClassifier::Data::Stage* cascadeStages = &cascade.data.stages[0];
335 for( int si = 0; si < nstages; si++ )
337 CascadeClassifier::Data::Stage& stage = cascadeStages[si];
338 int wi, ntrees = stage.ntrees;
341 for( wi = 0; wi < ntrees; wi++ )
343 CascadeClassifier::Data::DTree& weak = cascadeWeaks[stage.first + wi];
344 int idx = 0, root = nodeOfs;
348 CascadeClassifier::Data::DTreeNode& node = cascadeNodes[root + idx];
349 double val = featureEvaluator(node.featureIdx);
350 idx = val < node.threshold ? node.left : node.right;
353 sum += cascadeLeaves[leafOfs - idx];
354 nodeOfs += weak.nodeCount;
355 leafOfs += weak.nodeCount + 1;
357 if( sum < stage.threshold )
363 template<class FEval>
364 inline int predictCategorical( CascadeClassifier& cascade, Ptr<FeatureEvaluator> &_featureEvaluator, double& sum )
366 int nstages = (int)cascade.data.stages.size();
367 int nodeOfs = 0, leafOfs = 0;
368 FEval& featureEvaluator = (FEval&)*_featureEvaluator;
369 size_t subsetSize = (cascade.data.ncategories + 31)/32;
370 int* cascadeSubsets = &cascade.data.subsets[0];
371 float* cascadeLeaves = &cascade.data.leaves[0];
372 CascadeClassifier::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0];
373 CascadeClassifier::Data::DTree* cascadeWeaks = &cascade.data.classifiers[0];
374 CascadeClassifier::Data::Stage* cascadeStages = &cascade.data.stages[0];
376 for(int si = 0; si < nstages; si++ )
378 CascadeClassifier::Data::Stage& stage = cascadeStages[si];
379 int wi, ntrees = stage.ntrees;
382 for( wi = 0; wi < ntrees; wi++ )
384 CascadeClassifier::Data::DTree& weak = cascadeWeaks[stage.first + wi];
385 int idx = 0, root = nodeOfs;
388 CascadeClassifier::Data::DTreeNode& node = cascadeNodes[root + idx];
389 int c = featureEvaluator(node.featureIdx);
390 const int* subset = &cascadeSubsets[(root + idx)*subsetSize];
391 idx = (subset[c>>5] & (1 << (c & 31))) ? node.left : node.right;
394 sum += cascadeLeaves[leafOfs - idx];
395 nodeOfs += weak.nodeCount;
396 leafOfs += weak.nodeCount + 1;
398 if( sum < stage.threshold )
404 template<class FEval>
405 inline int predictOrderedStump( CascadeClassifier& cascade, Ptr<FeatureEvaluator> &_featureEvaluator, double& sum )
407 int nodeOfs = 0, leafOfs = 0;
408 FEval& featureEvaluator = (FEval&)*_featureEvaluator;
409 float* cascadeLeaves = &cascade.data.leaves[0];
410 CascadeClassifier::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0];
411 CascadeClassifier::Data::Stage* cascadeStages = &cascade.data.stages[0];
413 int nstages = (int)cascade.data.stages.size();
414 for( int stageIdx = 0; stageIdx < nstages; stageIdx++ )
416 CascadeClassifier::Data::Stage& stage = cascadeStages[stageIdx];
419 int ntrees = stage.ntrees;
420 for( int i = 0; i < ntrees; i++, nodeOfs++, leafOfs+= 2 )
422 CascadeClassifier::Data::DTreeNode& node = cascadeNodes[nodeOfs];
423 double value = featureEvaluator(node.featureIdx);
424 sum += cascadeLeaves[ value < node.threshold ? leafOfs : leafOfs + 1 ];
427 if( sum < stage.threshold )
434 template<class FEval>
435 inline int predictCategoricalStump( CascadeClassifier& cascade, Ptr<FeatureEvaluator> &_featureEvaluator, double& sum )
437 int nstages = (int)cascade.data.stages.size();
438 int nodeOfs = 0, leafOfs = 0;
439 FEval& featureEvaluator = (FEval&)*_featureEvaluator;
440 size_t subsetSize = (cascade.data.ncategories + 31)/32;
441 int* cascadeSubsets = &cascade.data.subsets[0];
442 float* cascadeLeaves = &cascade.data.leaves[0];
443 CascadeClassifier::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0];
444 CascadeClassifier::Data::Stage* cascadeStages = &cascade.data.stages[0];
446 #ifdef HAVE_TEGRA_OPTIMIZATION
447 float tmp = 0; // float accumulator -- float operations are quicker
449 for( int si = 0; si < nstages; si++ )
451 CascadeClassifier::Data::Stage& stage = cascadeStages[si];
452 int wi, ntrees = stage.ntrees;
453 #ifdef HAVE_TEGRA_OPTIMIZATION
459 for( wi = 0; wi < ntrees; wi++ )
461 CascadeClassifier::Data::DTreeNode& node = cascadeNodes[nodeOfs];
462 int c = featureEvaluator(node.featureIdx);
463 const int* subset = &cascadeSubsets[nodeOfs*subsetSize];
464 #ifdef HAVE_TEGRA_OPTIMIZATION
465 tmp += cascadeLeaves[ subset[c>>5] & (1 << (c & 31)) ? leafOfs : leafOfs+1];
467 sum += cascadeLeaves[ subset[c>>5] & (1 << (c & 31)) ? leafOfs : leafOfs+1];
472 #ifdef HAVE_TEGRA_OPTIMIZATION
473 if( tmp < stage.threshold ) {
478 if( sum < stage.threshold )
483 #ifdef HAVE_TEGRA_OPTIMIZATION