Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/objdetect/src/cascadedetect.hpp
16337 views
1
#pragma once
2
3
#include "opencv2/core/ocl.hpp"
4
5
namespace cv
6
{
7
8
void clipObjects(Size sz, std::vector<Rect>& objects,
9
std::vector<int>* a, std::vector<double>* b);
10
11
class FeatureEvaluator
12
{
13
public:
14
enum
15
{
16
HAAR = 0,
17
LBP = 1,
18
HOG = 2
19
};
20
21
struct ScaleData
22
{
23
ScaleData() { scale = 0.f; layer_ofs = ystep = 0; }
24
Size getWorkingSize(Size winSize) const
25
{
26
return Size(std::max(szi.width - winSize.width, 0),
27
std::max(szi.height - winSize.height, 0));
28
}
29
30
float scale;
31
Size szi;
32
int layer_ofs, ystep;
33
};
34
35
virtual ~FeatureEvaluator();
36
37
virtual bool read(const FileNode& node, Size origWinSize);
38
virtual Ptr<FeatureEvaluator> clone() const;
39
virtual int getFeatureType() const;
40
int getNumChannels() const { return nchannels; }
41
42
virtual bool setImage(InputArray img, const std::vector<float>& scales);
43
virtual bool setWindow(Point p, int scaleIdx);
44
const ScaleData& getScaleData(int scaleIdx) const
45
{
46
CV_Assert( 0 <= scaleIdx && scaleIdx < (int)scaleData->size());
47
return scaleData->at(scaleIdx);
48
}
49
virtual void getUMats(std::vector<UMat>& bufs);
50
virtual void getMats();
51
52
Size getLocalSize() const { return localSize; }
53
Size getLocalBufSize() const { return lbufSize; }
54
55
virtual float calcOrd(int featureIdx) const;
56
virtual int calcCat(int featureIdx) const;
57
58
static Ptr<FeatureEvaluator> create(int type);
59
60
protected:
61
enum { SBUF_VALID=1, USBUF_VALID=2 };
62
int sbufFlag;
63
64
bool updateScaleData( Size imgsz, const std::vector<float>& _scales );
65
virtual void computeChannels( int, InputArray ) {}
66
virtual void computeOptFeatures() {}
67
68
Size origWinSize, sbufSize, localSize, lbufSize;
69
int nchannels;
70
Mat sbuf, rbuf;
71
UMat urbuf, usbuf, ufbuf, uscaleData;
72
73
Ptr<std::vector<ScaleData> > scaleData;
74
};
75
76
77
class CascadeClassifierImpl CV_FINAL : public BaseCascadeClassifier
78
{
79
public:
80
CascadeClassifierImpl();
81
virtual ~CascadeClassifierImpl() CV_OVERRIDE;
82
83
bool empty() const CV_OVERRIDE;
84
bool load( const String& filename ) CV_OVERRIDE;
85
void read( const FileNode& node ) CV_OVERRIDE;
86
bool read_( const FileNode& node );
87
void detectMultiScale( InputArray image,
88
CV_OUT std::vector<Rect>& objects,
89
double scaleFactor = 1.1,
90
int minNeighbors = 3, int flags = 0,
91
Size minSize = Size(),
92
Size maxSize = Size() ) CV_OVERRIDE;
93
94
void detectMultiScale( InputArray image,
95
CV_OUT std::vector<Rect>& objects,
96
CV_OUT std::vector<int>& numDetections,
97
double scaleFactor=1.1,
98
int minNeighbors=3, int flags=0,
99
Size minSize=Size(),
100
Size maxSize=Size() ) CV_OVERRIDE;
101
102
void detectMultiScale( InputArray image,
103
CV_OUT std::vector<Rect>& objects,
104
CV_OUT std::vector<int>& rejectLevels,
105
CV_OUT std::vector<double>& levelWeights,
106
double scaleFactor = 1.1,
107
int minNeighbors = 3, int flags = 0,
108
Size minSize = Size(),
109
Size maxSize = Size(),
110
bool outputRejectLevels = false ) CV_OVERRIDE;
111
112
113
bool isOldFormatCascade() const CV_OVERRIDE;
114
Size getOriginalWindowSize() const CV_OVERRIDE;
115
int getFeatureType() const CV_OVERRIDE;
116
void* getOldCascade() CV_OVERRIDE;
117
118
void setMaskGenerator(const Ptr<MaskGenerator>& maskGenerator) CV_OVERRIDE;
119
Ptr<MaskGenerator> getMaskGenerator() CV_OVERRIDE;
120
121
protected:
122
enum { SUM_ALIGN = 64 };
123
124
bool detectSingleScale( InputArray image, Size processingRectSize,
125
int yStep, double factor, std::vector<Rect>& candidates,
126
std::vector<int>& rejectLevels, std::vector<double>& levelWeights,
127
Size sumSize0, bool outputRejectLevels = false );
128
#ifdef HAVE_OPENCL
129
bool ocl_detectMultiScaleNoGrouping( const std::vector<float>& scales,
130
std::vector<Rect>& candidates );
131
#endif
132
void detectMultiScaleNoGrouping( InputArray image, std::vector<Rect>& candidates,
133
std::vector<int>& rejectLevels, std::vector<double>& levelWeights,
134
double scaleFactor, Size minObjectSize, Size maxObjectSize,
135
bool outputRejectLevels = false );
136
137
enum { MAX_FACES = 10000 };
138
enum { BOOST = 0 };
139
enum { DO_CANNY_PRUNING = CASCADE_DO_CANNY_PRUNING,
140
SCALE_IMAGE = CASCADE_SCALE_IMAGE,
141
FIND_BIGGEST_OBJECT = CASCADE_FIND_BIGGEST_OBJECT,
142
DO_ROUGH_SEARCH = CASCADE_DO_ROUGH_SEARCH
143
};
144
145
friend class CascadeClassifierInvoker;
146
friend class SparseCascadeClassifierInvoker;
147
148
template<class FEval>
149
friend int predictOrdered( CascadeClassifierImpl& cascade, Ptr<FeatureEvaluator> &featureEvaluator, double& weight);
150
151
template<class FEval>
152
friend int predictCategorical( CascadeClassifierImpl& cascade, Ptr<FeatureEvaluator> &featureEvaluator, double& weight);
153
154
template<class FEval>
155
friend int predictOrderedStump( CascadeClassifierImpl& cascade, Ptr<FeatureEvaluator> &featureEvaluator, double& weight);
156
157
template<class FEval>
158
friend int predictCategoricalStump( CascadeClassifierImpl& cascade, Ptr<FeatureEvaluator> &featureEvaluator, double& weight);
159
160
int runAt( Ptr<FeatureEvaluator>& feval, Point pt, int scaleIdx, double& weight );
161
162
class Data
163
{
164
public:
165
struct DTreeNode
166
{
167
int featureIdx;
168
float threshold; // for ordered features only
169
int left;
170
int right;
171
};
172
173
struct DTree
174
{
175
int nodeCount;
176
};
177
178
struct Stage
179
{
180
int first;
181
int ntrees;
182
float threshold;
183
};
184
185
struct Stump
186
{
187
Stump() : featureIdx(0), threshold(0), left(0), right(0) { }
188
Stump(int _featureIdx, float _threshold, float _left, float _right)
189
: featureIdx(_featureIdx), threshold(_threshold), left(_left), right(_right) {}
190
191
int featureIdx;
192
float threshold;
193
float left;
194
float right;
195
};
196
197
Data();
198
199
bool read(const FileNode &node);
200
201
int stageType;
202
int featureType;
203
int ncategories;
204
int minNodesPerTree, maxNodesPerTree;
205
Size origWinSize;
206
207
std::vector<Stage> stages;
208
std::vector<DTree> classifiers;
209
std::vector<DTreeNode> nodes;
210
std::vector<float> leaves;
211
std::vector<int> subsets;
212
std::vector<Stump> stumps;
213
};
214
215
Data data;
216
Ptr<FeatureEvaluator> featureEvaluator;
217
Ptr<CvHaarClassifierCascade> oldCascade;
218
219
Ptr<MaskGenerator> maskGenerator;
220
UMat ugrayImage;
221
UMat ufacepos, ustages, unodes, uleaves, usubsets;
222
#ifdef HAVE_OPENCL
223
ocl::Kernel haarKernel, lbpKernel;
224
bool tryOpenCL;
225
#endif
226
227
Mutex mtx;
228
};
229
230
#define CC_CASCADE_PARAMS "cascadeParams"
231
#define CC_STAGE_TYPE "stageType"
232
#define CC_FEATURE_TYPE "featureType"
233
#define CC_HEIGHT "height"
234
#define CC_WIDTH "width"
235
236
#define CC_STAGE_NUM "stageNum"
237
#define CC_STAGES "stages"
238
#define CC_STAGE_PARAMS "stageParams"
239
240
#define CC_BOOST "BOOST"
241
#define CC_MAX_DEPTH "maxDepth"
242
#define CC_WEAK_COUNT "maxWeakCount"
243
#define CC_STAGE_THRESHOLD "stageThreshold"
244
#define CC_WEAK_CLASSIFIERS "weakClassifiers"
245
#define CC_INTERNAL_NODES "internalNodes"
246
#define CC_LEAF_VALUES "leafValues"
247
248
#define CC_FEATURES "features"
249
#define CC_FEATURE_PARAMS "featureParams"
250
#define CC_MAX_CAT_COUNT "maxCatCount"
251
252
#define CC_HAAR "HAAR"
253
#define CC_RECTS "rects"
254
#define CC_TILTED "tilted"
255
256
#define CC_LBP "LBP"
257
#define CC_RECT "rect"
258
259
#define CC_HOG "HOG"
260
261
#define CV_SUM_PTRS( p0, p1, p2, p3, sum, rect, step ) \
262
/* (x, y) */ \
263
(p0) = sum + (rect).x + (step) * (rect).y, \
264
/* (x + w, y) */ \
265
(p1) = sum + (rect).x + (rect).width + (step) * (rect).y, \
266
/* (x, y + h) */ \
267
(p2) = sum + (rect).x + (step) * ((rect).y + (rect).height), \
268
/* (x + w, y + h) */ \
269
(p3) = sum + (rect).x + (rect).width + (step) * ((rect).y + (rect).height)
270
271
#define CV_TILTED_PTRS( p0, p1, p2, p3, tilted, rect, step ) \
272
/* (x, y) */ \
273
(p0) = tilted + (rect).x + (step) * (rect).y, \
274
/* (x - h, y + h) */ \
275
(p1) = tilted + (rect).x - (rect).height + (step) * ((rect).y + (rect).height), \
276
/* (x + w, y + w) */ \
277
(p2) = tilted + (rect).x + (rect).width + (step) * ((rect).y + (rect).width), \
278
/* (x + w - h, y + w + h) */ \
279
(p3) = tilted + (rect).x + (rect).width - (rect).height \
280
+ (step) * ((rect).y + (rect).width + (rect).height)
281
282
#define CALC_SUM_(p0, p1, p2, p3, offset) \
283
((p0)[offset] - (p1)[offset] - (p2)[offset] + (p3)[offset])
284
285
#define CALC_SUM(rect,offset) CALC_SUM_((rect)[0], (rect)[1], (rect)[2], (rect)[3], offset)
286
287
#define CV_SUM_OFS( p0, p1, p2, p3, sum, rect, step ) \
288
/* (x, y) */ \
289
(p0) = sum + (rect).x + (step) * (rect).y, \
290
/* (x + w, y) */ \
291
(p1) = sum + (rect).x + (rect).width + (step) * (rect).y, \
292
/* (x, y + h) */ \
293
(p2) = sum + (rect).x + (step) * ((rect).y + (rect).height), \
294
/* (x + w, y + h) */ \
295
(p3) = sum + (rect).x + (rect).width + (step) * ((rect).y + (rect).height)
296
297
#define CV_TILTED_OFS( p0, p1, p2, p3, tilted, rect, step ) \
298
/* (x, y) */ \
299
(p0) = tilted + (rect).x + (step) * (rect).y, \
300
/* (x - h, y + h) */ \
301
(p1) = tilted + (rect).x - (rect).height + (step) * ((rect).y + (rect).height), \
302
/* (x + w, y + w) */ \
303
(p2) = tilted + (rect).x + (rect).width + (step) * ((rect).y + (rect).width), \
304
/* (x + w - h, y + w + h) */ \
305
(p3) = tilted + (rect).x + (rect).width - (rect).height \
306
+ (step) * ((rect).y + (rect).width + (rect).height)
307
308
#define CALC_SUM_OFS_(p0, p1, p2, p3, ptr) \
309
((ptr)[p0] - (ptr)[p1] - (ptr)[p2] + (ptr)[p3])
310
311
#define CALC_SUM_OFS(rect, ptr) CALC_SUM_OFS_((rect)[0], (rect)[1], (rect)[2], (rect)[3], ptr)
312
313
//---------------------------------------------- HaarEvaluator ---------------------------------------
314
class HaarEvaluator CV_FINAL : public FeatureEvaluator
315
{
316
public:
317
struct Feature
318
{
319
Feature();
320
bool read( const FileNode& node );
321
322
bool tilted;
323
324
enum { RECT_NUM = 3 };
325
struct
326
{
327
Rect r;
328
float weight;
329
} rect[RECT_NUM];
330
};
331
332
struct OptFeature
333
{
334
OptFeature();
335
336
enum { RECT_NUM = Feature::RECT_NUM };
337
float calc( const int* pwin ) const;
338
void setOffsets( const Feature& _f, int step, int tofs );
339
340
int ofs[RECT_NUM][4];
341
float weight[4];
342
};
343
344
HaarEvaluator();
345
virtual ~HaarEvaluator() CV_OVERRIDE;
346
347
virtual bool read( const FileNode& node, Size origWinSize) CV_OVERRIDE;
348
virtual Ptr<FeatureEvaluator> clone() const CV_OVERRIDE;
349
virtual int getFeatureType() const CV_OVERRIDE { return FeatureEvaluator::HAAR; }
350
351
virtual bool setWindow(Point p, int scaleIdx) CV_OVERRIDE;
352
Rect getNormRect() const;
353
int getSquaresOffset() const;
354
355
float operator()(int featureIdx) const
356
{ return optfeaturesPtr[featureIdx].calc(pwin) * varianceNormFactor; }
357
virtual float calcOrd(int featureIdx) const CV_OVERRIDE
358
{ return (*this)(featureIdx); }
359
360
protected:
361
virtual void computeChannels( int i, InputArray img ) CV_OVERRIDE;
362
virtual void computeOptFeatures() CV_OVERRIDE;
363
364
Ptr<std::vector<Feature> > features;
365
Ptr<std::vector<OptFeature> > optfeatures;
366
Ptr<std::vector<OptFeature> > optfeatures_lbuf;
367
bool hasTiltedFeatures;
368
369
int tofs, sqofs;
370
Vec4i nofs;
371
Rect normrect;
372
const int* pwin;
373
OptFeature* optfeaturesPtr; // optimization
374
float varianceNormFactor;
375
};
376
377
inline HaarEvaluator::Feature :: Feature()
378
{
379
tilted = false;
380
rect[0].r = rect[1].r = rect[2].r = Rect();
381
rect[0].weight = rect[1].weight = rect[2].weight = 0;
382
}
383
384
inline HaarEvaluator::OptFeature :: OptFeature()
385
{
386
weight[0] = weight[1] = weight[2] = 0.f;
387
388
ofs[0][0] = ofs[0][1] = ofs[0][2] = ofs[0][3] =
389
ofs[1][0] = ofs[1][1] = ofs[1][2] = ofs[1][3] =
390
ofs[2][0] = ofs[2][1] = ofs[2][2] = ofs[2][3] = 0;
391
}
392
393
inline float HaarEvaluator::OptFeature :: calc( const int* ptr ) const
394
{
395
float ret = weight[0] * CALC_SUM_OFS(ofs[0], ptr) +
396
weight[1] * CALC_SUM_OFS(ofs[1], ptr);
397
398
if( weight[2] != 0.0f )
399
ret += weight[2] * CALC_SUM_OFS(ofs[2], ptr);
400
401
return ret;
402
}
403
404
//---------------------------------------------- LBPEvaluator -------------------------------------
405
406
class LBPEvaluator CV_FINAL : public FeatureEvaluator
407
{
408
public:
409
struct Feature
410
{
411
Feature();
412
Feature( int x, int y, int _block_w, int _block_h ) :
413
rect(x, y, _block_w, _block_h) {}
414
415
bool read(const FileNode& node );
416
417
Rect rect; // weight and height for block
418
};
419
420
struct OptFeature
421
{
422
OptFeature();
423
424
int calc( const int* pwin ) const;
425
void setOffsets( const Feature& _f, int step );
426
int ofs[16];
427
};
428
429
LBPEvaluator();
430
virtual ~LBPEvaluator() CV_OVERRIDE;
431
432
virtual bool read( const FileNode& node, Size origWinSize ) CV_OVERRIDE;
433
virtual Ptr<FeatureEvaluator> clone() const CV_OVERRIDE;
434
virtual int getFeatureType() const CV_OVERRIDE { return FeatureEvaluator::LBP; }
435
436
virtual bool setWindow(Point p, int scaleIdx) CV_OVERRIDE;
437
438
int operator()(int featureIdx) const
439
{ return optfeaturesPtr[featureIdx].calc(pwin); }
440
virtual int calcCat(int featureIdx) const CV_OVERRIDE
441
{ return (*this)(featureIdx); }
442
protected:
443
virtual void computeChannels( int i, InputArray img ) CV_OVERRIDE;
444
virtual void computeOptFeatures() CV_OVERRIDE;
445
446
Ptr<std::vector<Feature> > features;
447
Ptr<std::vector<OptFeature> > optfeatures;
448
Ptr<std::vector<OptFeature> > optfeatures_lbuf;
449
OptFeature* optfeaturesPtr; // optimization
450
451
const int* pwin;
452
};
453
454
455
inline LBPEvaluator::Feature :: Feature()
456
{
457
rect = Rect();
458
}
459
460
inline LBPEvaluator::OptFeature :: OptFeature()
461
{
462
for( int i = 0; i < 16; i++ )
463
ofs[i] = 0;
464
}
465
466
inline int LBPEvaluator::OptFeature :: calc( const int* p ) const
467
{
468
int cval = CALC_SUM_OFS_( ofs[5], ofs[6], ofs[9], ofs[10], p );
469
470
return (CALC_SUM_OFS_( ofs[0], ofs[1], ofs[4], ofs[5], p ) >= cval ? 128 : 0) | // 0
471
(CALC_SUM_OFS_( ofs[1], ofs[2], ofs[5], ofs[6], p ) >= cval ? 64 : 0) | // 1
472
(CALC_SUM_OFS_( ofs[2], ofs[3], ofs[6], ofs[7], p ) >= cval ? 32 : 0) | // 2
473
(CALC_SUM_OFS_( ofs[6], ofs[7], ofs[10], ofs[11], p ) >= cval ? 16 : 0) | // 5
474
(CALC_SUM_OFS_( ofs[10], ofs[11], ofs[14], ofs[15], p ) >= cval ? 8 : 0)| // 8
475
(CALC_SUM_OFS_( ofs[9], ofs[10], ofs[13], ofs[14], p ) >= cval ? 4 : 0)| // 7
476
(CALC_SUM_OFS_( ofs[8], ofs[9], ofs[12], ofs[13], p ) >= cval ? 2 : 0)| // 6
477
(CALC_SUM_OFS_( ofs[4], ofs[5], ofs[8], ofs[9], p ) >= cval ? 1 : 0);
478
}
479
480
481
//---------------------------------------------- predictor functions -------------------------------------
482
483
template<class FEval>
484
inline int predictOrdered( CascadeClassifierImpl& cascade,
485
Ptr<FeatureEvaluator> &_featureEvaluator, double& sum )
486
{
487
CV_INSTRUMENT_REGION();
488
489
int nstages = (int)cascade.data.stages.size();
490
int nodeOfs = 0, leafOfs = 0;
491
FEval& featureEvaluator = (FEval&)*_featureEvaluator;
492
float* cascadeLeaves = &cascade.data.leaves[0];
493
CascadeClassifierImpl::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0];
494
CascadeClassifierImpl::Data::DTree* cascadeWeaks = &cascade.data.classifiers[0];
495
CascadeClassifierImpl::Data::Stage* cascadeStages = &cascade.data.stages[0];
496
497
for( int si = 0; si < nstages; si++ )
498
{
499
CascadeClassifierImpl::Data::Stage& stage = cascadeStages[si];
500
int wi, ntrees = stage.ntrees;
501
sum = 0;
502
503
for( wi = 0; wi < ntrees; wi++ )
504
{
505
CascadeClassifierImpl::Data::DTree& weak = cascadeWeaks[stage.first + wi];
506
int idx = 0, root = nodeOfs;
507
508
do
509
{
510
CascadeClassifierImpl::Data::DTreeNode& node = cascadeNodes[root + idx];
511
double val = featureEvaluator(node.featureIdx);
512
idx = val < node.threshold ? node.left : node.right;
513
}
514
while( idx > 0 );
515
sum += cascadeLeaves[leafOfs - idx];
516
nodeOfs += weak.nodeCount;
517
leafOfs += weak.nodeCount + 1;
518
}
519
if( sum < stage.threshold )
520
return -si;
521
}
522
return 1;
523
}
524
525
template<class FEval>
526
inline int predictCategorical( CascadeClassifierImpl& cascade,
527
Ptr<FeatureEvaluator> &_featureEvaluator, double& sum )
528
{
529
CV_INSTRUMENT_REGION();
530
531
int nstages = (int)cascade.data.stages.size();
532
int nodeOfs = 0, leafOfs = 0;
533
FEval& featureEvaluator = (FEval&)*_featureEvaluator;
534
size_t subsetSize = (cascade.data.ncategories + 31)/32;
535
int* cascadeSubsets = &cascade.data.subsets[0];
536
float* cascadeLeaves = &cascade.data.leaves[0];
537
CascadeClassifierImpl::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0];
538
CascadeClassifierImpl::Data::DTree* cascadeWeaks = &cascade.data.classifiers[0];
539
CascadeClassifierImpl::Data::Stage* cascadeStages = &cascade.data.stages[0];
540
541
for(int si = 0; si < nstages; si++ )
542
{
543
CascadeClassifierImpl::Data::Stage& stage = cascadeStages[si];
544
int wi, ntrees = stage.ntrees;
545
sum = 0;
546
547
for( wi = 0; wi < ntrees; wi++ )
548
{
549
CascadeClassifierImpl::Data::DTree& weak = cascadeWeaks[stage.first + wi];
550
int idx = 0, root = nodeOfs;
551
do
552
{
553
CascadeClassifierImpl::Data::DTreeNode& node = cascadeNodes[root + idx];
554
int c = featureEvaluator(node.featureIdx);
555
const int* subset = &cascadeSubsets[(root + idx)*subsetSize];
556
idx = (subset[c>>5] & (1 << (c & 31))) ? node.left : node.right;
557
}
558
while( idx > 0 );
559
sum += cascadeLeaves[leafOfs - idx];
560
nodeOfs += weak.nodeCount;
561
leafOfs += weak.nodeCount + 1;
562
}
563
if( sum < stage.threshold )
564
return -si;
565
}
566
return 1;
567
}
568
569
template<class FEval>
570
inline int predictOrderedStump( CascadeClassifierImpl& cascade,
571
Ptr<FeatureEvaluator> &_featureEvaluator, double& sum )
572
{
573
CV_INSTRUMENT_REGION();
574
575
CV_Assert(!cascade.data.stumps.empty());
576
FEval& featureEvaluator = (FEval&)*_featureEvaluator;
577
const CascadeClassifierImpl::Data::Stump* cascadeStumps = &cascade.data.stumps[0];
578
const CascadeClassifierImpl::Data::Stage* cascadeStages = &cascade.data.stages[0];
579
580
int nstages = (int)cascade.data.stages.size();
581
double tmp = 0;
582
583
for( int stageIdx = 0; stageIdx < nstages; stageIdx++ )
584
{
585
const CascadeClassifierImpl::Data::Stage& stage = cascadeStages[stageIdx];
586
tmp = 0;
587
588
int ntrees = stage.ntrees;
589
for( int i = 0; i < ntrees; i++ )
590
{
591
const CascadeClassifierImpl::Data::Stump& stump = cascadeStumps[i];
592
double value = featureEvaluator(stump.featureIdx);
593
tmp += value < stump.threshold ? stump.left : stump.right;
594
}
595
596
if( tmp < stage.threshold )
597
{
598
sum = (double)tmp;
599
return -stageIdx;
600
}
601
cascadeStumps += ntrees;
602
}
603
604
sum = (double)tmp;
605
return 1;
606
}
607
608
template<class FEval>
609
inline int predictCategoricalStump( CascadeClassifierImpl& cascade,
610
Ptr<FeatureEvaluator> &_featureEvaluator, double& sum )
611
{
612
CV_INSTRUMENT_REGION();
613
614
CV_Assert(!cascade.data.stumps.empty());
615
int nstages = (int)cascade.data.stages.size();
616
FEval& featureEvaluator = (FEval&)*_featureEvaluator;
617
size_t subsetSize = (cascade.data.ncategories + 31)/32;
618
const int* cascadeSubsets = &cascade.data.subsets[0];
619
const CascadeClassifierImpl::Data::Stump* cascadeStumps = &cascade.data.stumps[0];
620
const CascadeClassifierImpl::Data::Stage* cascadeStages = &cascade.data.stages[0];
621
622
double tmp = 0;
623
for( int si = 0; si < nstages; si++ )
624
{
625
const CascadeClassifierImpl::Data::Stage& stage = cascadeStages[si];
626
int wi, ntrees = stage.ntrees;
627
tmp = 0;
628
629
for( wi = 0; wi < ntrees; wi++ )
630
{
631
const CascadeClassifierImpl::Data::Stump& stump = cascadeStumps[wi];
632
int c = featureEvaluator(stump.featureIdx);
633
const int* subset = &cascadeSubsets[wi*subsetSize];
634
tmp += (subset[c>>5] & (1 << (c & 31))) ? stump.left : stump.right;
635
}
636
637
if( tmp < stage.threshold )
638
{
639
sum = tmp;
640
return -si;
641
}
642
643
cascadeStumps += ntrees;
644
cascadeSubsets += ntrees*subsetSize;
645
}
646
647
sum = (double)tmp;
648
return 1;
649
}
650
}
651
652