mirror of https://github.com/opencv/opencv.git
Open Source Computer Vision Library
https://opencv.org/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
656 lines
22 KiB
656 lines
22 KiB
#pragma once |
|
|
|
#include "opencv2/core/ocl.hpp" |
|
|
|
namespace cv |
|
{ |
|
|
|
void clipObjects(Size sz, std::vector<Rect>& objects, |
|
std::vector<int>* a, std::vector<double>* b); |
|
|
|
class FeatureEvaluator |
|
{ |
|
public: |
|
enum |
|
{ |
|
HAAR = 0, |
|
LBP = 1, |
|
HOG = 2 |
|
}; |
|
|
|
struct ScaleData |
|
{ |
|
ScaleData() { scale = 0.f; layer_ofs = ystep = 0; } |
|
Size getWorkingSize(Size winSize) const |
|
{ |
|
return Size(std::max(szi.width - winSize.width, 0), |
|
std::max(szi.height - winSize.height, 0)); |
|
} |
|
|
|
float scale; |
|
Size szi; |
|
int layer_ofs, ystep; |
|
}; |
|
|
|
virtual ~FeatureEvaluator(); |
|
|
|
virtual bool read(const FileNode& node, Size origWinSize); |
|
virtual Ptr<FeatureEvaluator> clone() const; |
|
virtual int getFeatureType() const; |
|
int getNumChannels() const { return nchannels; } |
|
|
|
virtual bool setImage(InputArray img, const std::vector<float>& scales); |
|
virtual bool setWindow(Point p, int scaleIdx); |
|
const ScaleData& getScaleData(int scaleIdx) const |
|
{ |
|
CV_Assert( 0 <= scaleIdx && scaleIdx < (int)scaleData->size()); |
|
return scaleData->at(scaleIdx); |
|
} |
|
virtual void getUMats(std::vector<UMat>& bufs); |
|
virtual void getMats(); |
|
|
|
Size getLocalSize() const { return localSize; } |
|
Size getLocalBufSize() const { return lbufSize; } |
|
|
|
virtual float calcOrd(int featureIdx) const; |
|
virtual int calcCat(int featureIdx) const; |
|
|
|
static Ptr<FeatureEvaluator> create(int type); |
|
|
|
protected: |
|
enum { SBUF_VALID=1, USBUF_VALID=2 }; |
|
int sbufFlag; |
|
|
|
bool updateScaleData( Size imgsz, const std::vector<float>& _scales ); |
|
virtual void computeChannels( int, InputArray ) {} |
|
virtual void computeOptFeatures() {} |
|
|
|
Size origWinSize, sbufSize, localSize, lbufSize; |
|
int nchannels; |
|
Mat sbuf, rbuf; |
|
UMat urbuf, usbuf, ufbuf, uscaleData; |
|
|
|
Ptr<std::vector<ScaleData> > scaleData; |
|
}; |
|
|
|
|
|
class CascadeClassifierImpl CV_FINAL : public BaseCascadeClassifier |
|
{ |
|
public: |
|
CascadeClassifierImpl(); |
|
virtual ~CascadeClassifierImpl() CV_OVERRIDE; |
|
|
|
bool empty() const CV_OVERRIDE; |
|
bool load( const String& filename ) CV_OVERRIDE; |
|
void read( const FileNode& node ) CV_OVERRIDE; |
|
bool read_( const FileNode& node ); |
|
void detectMultiScale( InputArray image, |
|
CV_OUT std::vector<Rect>& objects, |
|
double scaleFactor = 1.1, |
|
int minNeighbors = 3, int flags = 0, |
|
Size minSize = Size(), |
|
Size maxSize = Size() ) CV_OVERRIDE; |
|
|
|
void detectMultiScale( InputArray image, |
|
CV_OUT std::vector<Rect>& objects, |
|
CV_OUT std::vector<int>& numDetections, |
|
double scaleFactor=1.1, |
|
int minNeighbors=3, int flags=0, |
|
Size minSize=Size(), |
|
Size maxSize=Size() ) CV_OVERRIDE; |
|
|
|
void detectMultiScale( InputArray image, |
|
CV_OUT std::vector<Rect>& objects, |
|
CV_OUT std::vector<int>& rejectLevels, |
|
CV_OUT std::vector<double>& levelWeights, |
|
double scaleFactor = 1.1, |
|
int minNeighbors = 3, int flags = 0, |
|
Size minSize = Size(), |
|
Size maxSize = Size(), |
|
bool outputRejectLevels = false ) CV_OVERRIDE; |
|
|
|
|
|
bool isOldFormatCascade() const CV_OVERRIDE; |
|
Size getOriginalWindowSize() const CV_OVERRIDE; |
|
int getFeatureType() const CV_OVERRIDE; |
|
void* getOldCascade() CV_OVERRIDE; |
|
|
|
void setMaskGenerator(const Ptr<MaskGenerator>& maskGenerator) CV_OVERRIDE; |
|
Ptr<MaskGenerator> getMaskGenerator() CV_OVERRIDE; |
|
|
|
protected: |
|
enum { SUM_ALIGN = 64 }; |
|
|
|
bool detectSingleScale( InputArray image, Size processingRectSize, |
|
int yStep, double factor, std::vector<Rect>& candidates, |
|
std::vector<int>& rejectLevels, std::vector<double>& levelWeights, |
|
Size sumSize0, bool outputRejectLevels = false ); |
|
#ifdef HAVE_OPENCL |
|
bool ocl_detectMultiScaleNoGrouping( const std::vector<float>& scales, |
|
std::vector<Rect>& candidates ); |
|
#endif |
|
void detectMultiScaleNoGrouping( InputArray image, std::vector<Rect>& candidates, |
|
std::vector<int>& rejectLevels, std::vector<double>& levelWeights, |
|
double scaleFactor, Size minObjectSize, Size maxObjectSize, |
|
bool outputRejectLevels = false ); |
|
|
|
enum { MAX_FACES = 10000 }; |
|
enum { BOOST = 0 }; |
|
enum { DO_CANNY_PRUNING = CASCADE_DO_CANNY_PRUNING, |
|
SCALE_IMAGE = CASCADE_SCALE_IMAGE, |
|
FIND_BIGGEST_OBJECT = CASCADE_FIND_BIGGEST_OBJECT, |
|
DO_ROUGH_SEARCH = CASCADE_DO_ROUGH_SEARCH |
|
}; |
|
|
|
friend class CascadeClassifierInvoker; |
|
friend class SparseCascadeClassifierInvoker; |
|
|
|
template<class FEval> |
|
friend int predictOrdered( CascadeClassifierImpl& cascade, Ptr<FeatureEvaluator> &featureEvaluator, double& weight); |
|
|
|
template<class FEval> |
|
friend int predictCategorical( CascadeClassifierImpl& cascade, Ptr<FeatureEvaluator> &featureEvaluator, double& weight); |
|
|
|
template<class FEval> |
|
friend int predictOrderedStump( CascadeClassifierImpl& cascade, Ptr<FeatureEvaluator> &featureEvaluator, double& weight); |
|
|
|
template<class FEval> |
|
friend int predictCategoricalStump( CascadeClassifierImpl& cascade, Ptr<FeatureEvaluator> &featureEvaluator, double& weight); |
|
|
|
int runAt( Ptr<FeatureEvaluator>& feval, Point pt, int scaleIdx, double& weight ); |
|
|
|
class Data |
|
{ |
|
public: |
|
struct DTreeNode |
|
{ |
|
int featureIdx; |
|
float threshold; // for ordered features only |
|
int left; |
|
int right; |
|
}; |
|
|
|
struct DTree |
|
{ |
|
int nodeCount; |
|
}; |
|
|
|
struct Stage |
|
{ |
|
int first; |
|
int ntrees; |
|
float threshold; |
|
}; |
|
|
|
struct Stump |
|
{ |
|
Stump() : featureIdx(0), threshold(0), left(0), right(0) { } |
|
Stump(int _featureIdx, float _threshold, float _left, float _right) |
|
: featureIdx(_featureIdx), threshold(_threshold), left(_left), right(_right) {} |
|
|
|
int featureIdx; |
|
float threshold; |
|
float left; |
|
float right; |
|
}; |
|
|
|
Data(); |
|
|
|
bool read(const FileNode &node); |
|
|
|
int stageType; |
|
int featureType; |
|
int ncategories; |
|
int minNodesPerTree, maxNodesPerTree; |
|
Size origWinSize; |
|
|
|
std::vector<Stage> stages; |
|
std::vector<DTree> classifiers; |
|
std::vector<DTreeNode> nodes; |
|
std::vector<float> leaves; |
|
std::vector<int> subsets; |
|
std::vector<Stump> stumps; |
|
}; |
|
|
|
Data data; |
|
Ptr<FeatureEvaluator> featureEvaluator; |
|
Ptr<CvHaarClassifierCascade> oldCascade; |
|
|
|
Ptr<MaskGenerator> maskGenerator; |
|
UMat ugrayImage; |
|
UMat ufacepos, ustages, unodes, uleaves, usubsets; |
|
#ifdef HAVE_OPENCL |
|
ocl::Kernel haarKernel, lbpKernel; |
|
bool tryOpenCL; |
|
#endif |
|
|
|
Mutex mtx; |
|
}; |
|
|
|
#define CC_CASCADE_PARAMS "cascadeParams" |
|
#define CC_STAGE_TYPE "stageType" |
|
#define CC_FEATURE_TYPE "featureType" |
|
#define CC_HEIGHT "height" |
|
#define CC_WIDTH "width" |
|
|
|
#define CC_STAGE_NUM "stageNum" |
|
#define CC_STAGES "stages" |
|
#define CC_STAGE_PARAMS "stageParams" |
|
|
|
#define CC_BOOST "BOOST" |
|
#define CC_MAX_DEPTH "maxDepth" |
|
#define CC_WEAK_COUNT "maxWeakCount" |
|
#define CC_STAGE_THRESHOLD "stageThreshold" |
|
#define CC_WEAK_CLASSIFIERS "weakClassifiers" |
|
#define CC_INTERNAL_NODES "internalNodes" |
|
#define CC_LEAF_VALUES "leafValues" |
|
|
|
#define CC_FEATURES "features" |
|
#define CC_FEATURE_PARAMS "featureParams" |
|
#define CC_MAX_CAT_COUNT "maxCatCount" |
|
|
|
#define CC_HAAR "HAAR" |
|
#define CC_RECTS "rects" |
|
#define CC_TILTED "tilted" |
|
|
|
#define CC_LBP "LBP" |
|
#define CC_RECT "rect" |
|
|
|
#define CC_HOG "HOG" |
|
|
|
#define CV_SUM_PTRS( p0, p1, p2, p3, sum, rect, step ) \ |
|
/* (x, y) */ \ |
|
(p0) = sum + (rect).x + (step) * (rect).y, \ |
|
/* (x + w, y) */ \ |
|
(p1) = sum + (rect).x + (rect).width + (step) * (rect).y, \ |
|
/* (x, y + h) */ \ |
|
(p2) = sum + (rect).x + (step) * ((rect).y + (rect).height), \ |
|
/* (x + w, y + h) */ \ |
|
(p3) = sum + (rect).x + (rect).width + (step) * ((rect).y + (rect).height) |
|
|
|
#define CV_TILTED_PTRS( p0, p1, p2, p3, tilted, rect, step ) \ |
|
/* (x, y) */ \ |
|
(p0) = tilted + (rect).x + (step) * (rect).y, \ |
|
/* (x - h, y + h) */ \ |
|
(p1) = tilted + (rect).x - (rect).height + (step) * ((rect).y + (rect).height), \ |
|
/* (x + w, y + w) */ \ |
|
(p2) = tilted + (rect).x + (rect).width + (step) * ((rect).y + (rect).width), \ |
|
/* (x + w - h, y + w + h) */ \ |
|
(p3) = tilted + (rect).x + (rect).width - (rect).height \ |
|
+ (step) * ((rect).y + (rect).width + (rect).height) |
|
|
|
#define CALC_SUM_(p0, p1, p2, p3, offset) \ |
|
((p0)[offset] - (p1)[offset] - (p2)[offset] + (p3)[offset]) |
|
|
|
#define CALC_SUM(rect,offset) CALC_SUM_((rect)[0], (rect)[1], (rect)[2], (rect)[3], offset) |
|
|
|
#define CV_SUM_OFS( p0, p1, p2, p3, sum, rect, step ) \ |
|
/* (x, y) */ \ |
|
(p0) = sum + (rect).x + (step) * (rect).y, \ |
|
/* (x + w, y) */ \ |
|
(p1) = sum + (rect).x + (rect).width + (step) * (rect).y, \ |
|
/* (x, y + h) */ \ |
|
(p2) = sum + (rect).x + (step) * ((rect).y + (rect).height), \ |
|
/* (x + w, y + h) */ \ |
|
(p3) = sum + (rect).x + (rect).width + (step) * ((rect).y + (rect).height) |
|
|
|
#define CV_TILTED_OFS( p0, p1, p2, p3, tilted, rect, step ) \ |
|
/* (x, y) */ \ |
|
(p0) = tilted + (rect).x + (step) * (rect).y, \ |
|
/* (x - h, y + h) */ \ |
|
(p1) = tilted + (rect).x - (rect).height + (step) * ((rect).y + (rect).height), \ |
|
/* (x + w, y + w) */ \ |
|
(p2) = tilted + (rect).x + (rect).width + (step) * ((rect).y + (rect).width), \ |
|
/* (x + w - h, y + w + h) */ \ |
|
(p3) = tilted + (rect).x + (rect).width - (rect).height \ |
|
+ (step) * ((rect).y + (rect).width + (rect).height) |
|
|
|
#define CALC_SUM_OFS_(p0, p1, p2, p3, ptr) \ |
|
((ptr)[p0] - (ptr)[p1] - (ptr)[p2] + (ptr)[p3]) |
|
|
|
#define CALC_SUM_OFS(rect, ptr) CALC_SUM_OFS_((rect)[0], (rect)[1], (rect)[2], (rect)[3], ptr) |
|
|
|
//---------------------------------------------- HaarEvaluator --------------------------------------- |
|
class HaarEvaluator CV_FINAL : public FeatureEvaluator |
|
{ |
|
public: |
|
struct Feature |
|
{ |
|
Feature(); |
|
bool read(const FileNode& node, const Size& origWinSize); |
|
|
|
bool tilted; |
|
|
|
enum { RECT_NUM = 3 }; |
|
struct RectWeigth |
|
{ |
|
Rect r; |
|
float weight; |
|
} rect[RECT_NUM]; |
|
}; |
|
|
|
struct OptFeature |
|
{ |
|
OptFeature(); |
|
|
|
enum { RECT_NUM = Feature::RECT_NUM }; |
|
float calc( const int* pwin ) const; |
|
void setOffsets( const Feature& _f, int step, int tofs ); |
|
|
|
int ofs[RECT_NUM][4]; |
|
float weight[4]; |
|
}; |
|
|
|
HaarEvaluator(); |
|
virtual ~HaarEvaluator() CV_OVERRIDE; |
|
|
|
virtual bool read( const FileNode& node, Size origWinSize) CV_OVERRIDE; |
|
virtual Ptr<FeatureEvaluator> clone() const CV_OVERRIDE; |
|
virtual int getFeatureType() const CV_OVERRIDE { return FeatureEvaluator::HAAR; } |
|
|
|
virtual bool setWindow(Point p, int scaleIdx) CV_OVERRIDE; |
|
Rect getNormRect() const; |
|
int getSquaresOffset() const; |
|
|
|
float operator()(int featureIdx) const |
|
{ return optfeaturesPtr[featureIdx].calc(pwin) * varianceNormFactor; } |
|
virtual float calcOrd(int featureIdx) const CV_OVERRIDE |
|
{ return (*this)(featureIdx); } |
|
|
|
protected: |
|
virtual void computeChannels( int i, InputArray img ) CV_OVERRIDE; |
|
virtual void computeOptFeatures() CV_OVERRIDE; |
|
|
|
Ptr<std::vector<Feature> > features; |
|
Ptr<std::vector<OptFeature> > optfeatures; |
|
Ptr<std::vector<OptFeature> > optfeatures_lbuf; |
|
bool hasTiltedFeatures; |
|
|
|
int tofs, sqofs; |
|
Vec4i nofs; |
|
Rect normrect; |
|
const int* pwin; |
|
OptFeature* optfeaturesPtr; // optimization |
|
float varianceNormFactor; |
|
}; |
|
|
|
inline HaarEvaluator::Feature :: Feature() |
|
{ |
|
tilted = false; |
|
rect[0].r = rect[1].r = rect[2].r = Rect(); |
|
rect[0].weight = rect[1].weight = rect[2].weight = 0; |
|
} |
|
|
|
inline HaarEvaluator::OptFeature :: OptFeature() |
|
{ |
|
weight[0] = weight[1] = weight[2] = 0.f; |
|
|
|
ofs[0][0] = ofs[0][1] = ofs[0][2] = ofs[0][3] = |
|
ofs[1][0] = ofs[1][1] = ofs[1][2] = ofs[1][3] = |
|
ofs[2][0] = ofs[2][1] = ofs[2][2] = ofs[2][3] = 0; |
|
} |
|
|
|
inline float HaarEvaluator::OptFeature :: calc( const int* ptr ) const |
|
{ |
|
float ret = weight[0] * CALC_SUM_OFS(ofs[0], ptr) + |
|
weight[1] * CALC_SUM_OFS(ofs[1], ptr); |
|
|
|
if( weight[2] != 0.0f ) |
|
ret += weight[2] * CALC_SUM_OFS(ofs[2], ptr); |
|
|
|
return ret; |
|
} |
|
|
|
//---------------------------------------------- LBPEvaluator ------------------------------------- |
|
|
|
class LBPEvaluator CV_FINAL : public FeatureEvaluator |
|
{ |
|
public: |
|
struct Feature |
|
{ |
|
Feature(); |
|
Feature( int x, int y, int _block_w, int _block_h ) : |
|
rect(x, y, _block_w, _block_h) {} |
|
|
|
bool read(const FileNode& node, const Size& origWinSize); |
|
|
|
Rect rect; // weight and height for block |
|
}; |
|
|
|
struct OptFeature |
|
{ |
|
OptFeature(); |
|
|
|
int calc( const int* pwin ) const; |
|
void setOffsets( const Feature& _f, int step ); |
|
int ofs[16]; |
|
}; |
|
|
|
LBPEvaluator(); |
|
virtual ~LBPEvaluator() CV_OVERRIDE; |
|
|
|
virtual bool read( const FileNode& node, Size origWinSize ) CV_OVERRIDE; |
|
virtual Ptr<FeatureEvaluator> clone() const CV_OVERRIDE; |
|
virtual int getFeatureType() const CV_OVERRIDE { return FeatureEvaluator::LBP; } |
|
|
|
virtual bool setWindow(Point p, int scaleIdx) CV_OVERRIDE; |
|
|
|
int operator()(int featureIdx) const |
|
{ return optfeaturesPtr[featureIdx].calc(pwin); } |
|
virtual int calcCat(int featureIdx) const CV_OVERRIDE |
|
{ return (*this)(featureIdx); } |
|
protected: |
|
virtual void computeChannels( int i, InputArray img ) CV_OVERRIDE; |
|
virtual void computeOptFeatures() CV_OVERRIDE; |
|
|
|
Ptr<std::vector<Feature> > features; |
|
Ptr<std::vector<OptFeature> > optfeatures; |
|
Ptr<std::vector<OptFeature> > optfeatures_lbuf; |
|
OptFeature* optfeaturesPtr; // optimization |
|
|
|
const int* pwin; |
|
}; |
|
|
|
|
|
inline LBPEvaluator::Feature :: Feature() |
|
{ |
|
rect = Rect(); |
|
} |
|
|
|
inline LBPEvaluator::OptFeature :: OptFeature() |
|
{ |
|
for( int i = 0; i < 16; i++ ) |
|
ofs[i] = 0; |
|
} |
|
|
|
inline int LBPEvaluator::OptFeature :: calc( const int* p ) const |
|
{ |
|
int cval = CALC_SUM_OFS_( ofs[5], ofs[6], ofs[9], ofs[10], p ); |
|
|
|
return (CALC_SUM_OFS_( ofs[0], ofs[1], ofs[4], ofs[5], p ) >= cval ? 128 : 0) | // 0 |
|
(CALC_SUM_OFS_( ofs[1], ofs[2], ofs[5], ofs[6], p ) >= cval ? 64 : 0) | // 1 |
|
(CALC_SUM_OFS_( ofs[2], ofs[3], ofs[6], ofs[7], p ) >= cval ? 32 : 0) | // 2 |
|
(CALC_SUM_OFS_( ofs[6], ofs[7], ofs[10], ofs[11], p ) >= cval ? 16 : 0) | // 5 |
|
(CALC_SUM_OFS_( ofs[10], ofs[11], ofs[14], ofs[15], p ) >= cval ? 8 : 0)| // 8 |
|
(CALC_SUM_OFS_( ofs[9], ofs[10], ofs[13], ofs[14], p ) >= cval ? 4 : 0)| // 7 |
|
(CALC_SUM_OFS_( ofs[8], ofs[9], ofs[12], ofs[13], p ) >= cval ? 2 : 0)| // 6 |
|
(CALC_SUM_OFS_( ofs[4], ofs[5], ofs[8], ofs[9], p ) >= cval ? 1 : 0); |
|
} |
|
|
|
|
|
//---------------------------------------------- predictor functions ------------------------------------- |
|
|
|
template<class FEval> |
|
inline int predictOrdered( CascadeClassifierImpl& cascade, |
|
Ptr<FeatureEvaluator> &_featureEvaluator, double& sum ) |
|
{ |
|
CV_INSTRUMENT_REGION(); |
|
|
|
int nstages = (int)cascade.data.stages.size(); |
|
int nodeOfs = 0, leafOfs = 0; |
|
FEval& featureEvaluator = (FEval&)*_featureEvaluator; |
|
float* cascadeLeaves = &cascade.data.leaves[0]; |
|
CascadeClassifierImpl::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0]; |
|
CascadeClassifierImpl::Data::DTree* cascadeWeaks = &cascade.data.classifiers[0]; |
|
CascadeClassifierImpl::Data::Stage* cascadeStages = &cascade.data.stages[0]; |
|
|
|
for( int si = 0; si < nstages; si++ ) |
|
{ |
|
CascadeClassifierImpl::Data::Stage& stage = cascadeStages[si]; |
|
int wi, ntrees = stage.ntrees; |
|
sum = 0; |
|
|
|
for( wi = 0; wi < ntrees; wi++ ) |
|
{ |
|
CascadeClassifierImpl::Data::DTree& weak = cascadeWeaks[stage.first + wi]; |
|
int idx = 0, root = nodeOfs; |
|
|
|
do |
|
{ |
|
CascadeClassifierImpl::Data::DTreeNode& node = cascadeNodes[root + idx]; |
|
double val = featureEvaluator(node.featureIdx); |
|
idx = val < node.threshold ? node.left : node.right; |
|
} |
|
while( idx > 0 ); |
|
sum += cascadeLeaves[leafOfs - idx]; |
|
nodeOfs += weak.nodeCount; |
|
leafOfs += weak.nodeCount + 1; |
|
} |
|
if( sum < stage.threshold ) |
|
return -si; |
|
} |
|
return 1; |
|
} |
|
|
|
template<class FEval> |
|
inline int predictCategorical( CascadeClassifierImpl& cascade, |
|
Ptr<FeatureEvaluator> &_featureEvaluator, double& sum ) |
|
{ |
|
CV_INSTRUMENT_REGION(); |
|
|
|
int nstages = (int)cascade.data.stages.size(); |
|
int nodeOfs = 0, leafOfs = 0; |
|
FEval& featureEvaluator = (FEval&)*_featureEvaluator; |
|
size_t subsetSize = (cascade.data.ncategories + 31)/32; |
|
int* cascadeSubsets = &cascade.data.subsets[0]; |
|
float* cascadeLeaves = &cascade.data.leaves[0]; |
|
CascadeClassifierImpl::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0]; |
|
CascadeClassifierImpl::Data::DTree* cascadeWeaks = &cascade.data.classifiers[0]; |
|
CascadeClassifierImpl::Data::Stage* cascadeStages = &cascade.data.stages[0]; |
|
|
|
for(int si = 0; si < nstages; si++ ) |
|
{ |
|
CascadeClassifierImpl::Data::Stage& stage = cascadeStages[si]; |
|
int wi, ntrees = stage.ntrees; |
|
sum = 0; |
|
|
|
for( wi = 0; wi < ntrees; wi++ ) |
|
{ |
|
CascadeClassifierImpl::Data::DTree& weak = cascadeWeaks[stage.first + wi]; |
|
int idx = 0, root = nodeOfs; |
|
do |
|
{ |
|
CascadeClassifierImpl::Data::DTreeNode& node = cascadeNodes[root + idx]; |
|
int c = featureEvaluator(node.featureIdx); |
|
const int* subset = &cascadeSubsets[(root + idx)*subsetSize]; |
|
idx = (subset[c>>5] & (1 << (c & 31))) ? node.left : node.right; |
|
} |
|
while( idx > 0 ); |
|
sum += cascadeLeaves[leafOfs - idx]; |
|
nodeOfs += weak.nodeCount; |
|
leafOfs += weak.nodeCount + 1; |
|
} |
|
if( sum < stage.threshold ) |
|
return -si; |
|
} |
|
return 1; |
|
} |
|
|
|
template<class FEval> |
|
inline int predictOrderedStump( CascadeClassifierImpl& cascade, |
|
Ptr<FeatureEvaluator> &_featureEvaluator, double& sum ) |
|
{ |
|
CV_INSTRUMENT_REGION(); |
|
|
|
CV_Assert(!cascade.data.stumps.empty()); |
|
FEval& featureEvaluator = (FEval&)*_featureEvaluator; |
|
const CascadeClassifierImpl::Data::Stump* cascadeStumps = &cascade.data.stumps[0]; |
|
const CascadeClassifierImpl::Data::Stage* cascadeStages = &cascade.data.stages[0]; |
|
|
|
int nstages = (int)cascade.data.stages.size(); |
|
double tmp = 0; |
|
|
|
for( int stageIdx = 0; stageIdx < nstages; stageIdx++ ) |
|
{ |
|
const CascadeClassifierImpl::Data::Stage& stage = cascadeStages[stageIdx]; |
|
tmp = 0; |
|
|
|
int ntrees = stage.ntrees; |
|
for( int i = 0; i < ntrees; i++ ) |
|
{ |
|
const CascadeClassifierImpl::Data::Stump& stump = cascadeStumps[i]; |
|
double value = featureEvaluator(stump.featureIdx); |
|
tmp += value < stump.threshold ? stump.left : stump.right; |
|
} |
|
|
|
if( tmp < stage.threshold ) |
|
{ |
|
sum = (double)tmp; |
|
return -stageIdx; |
|
} |
|
cascadeStumps += ntrees; |
|
} |
|
|
|
sum = (double)tmp; |
|
return 1; |
|
} |
|
|
|
template<class FEval> |
|
inline int predictCategoricalStump( CascadeClassifierImpl& cascade, |
|
Ptr<FeatureEvaluator> &_featureEvaluator, double& sum ) |
|
{ |
|
CV_INSTRUMENT_REGION(); |
|
|
|
CV_Assert(!cascade.data.stumps.empty()); |
|
int nstages = (int)cascade.data.stages.size(); |
|
FEval& featureEvaluator = (FEval&)*_featureEvaluator; |
|
size_t subsetSize = (cascade.data.ncategories + 31)/32; |
|
const int* cascadeSubsets = &cascade.data.subsets[0]; |
|
const CascadeClassifierImpl::Data::Stump* cascadeStumps = &cascade.data.stumps[0]; |
|
const CascadeClassifierImpl::Data::Stage* cascadeStages = &cascade.data.stages[0]; |
|
|
|
double tmp = 0; |
|
for( int si = 0; si < nstages; si++ ) |
|
{ |
|
const CascadeClassifierImpl::Data::Stage& stage = cascadeStages[si]; |
|
int wi, ntrees = stage.ntrees; |
|
tmp = 0; |
|
|
|
for( wi = 0; wi < ntrees; wi++ ) |
|
{ |
|
const CascadeClassifierImpl::Data::Stump& stump = cascadeStumps[wi]; |
|
int c = featureEvaluator(stump.featureIdx); |
|
const int* subset = &cascadeSubsets[wi*subsetSize]; |
|
tmp += (subset[c>>5] & (1 << (c & 31))) ? stump.left : stump.right; |
|
} |
|
|
|
if( tmp < stage.threshold ) |
|
{ |
|
sum = tmp; |
|
return -si; |
|
} |
|
|
|
cascadeStumps += ntrees; |
|
cascadeSubsets += ntrees*subsetSize; |
|
} |
|
|
|
sum = (double)tmp; |
|
return 1; |
|
} |
|
|
|
namespace haar_cvt |
|
{ |
|
bool convert(const FileNode& oldcascade_root, FileStorage& newfs); |
|
} |
|
|
|
}
|
|
|