mirror of
https://github.com/opencv/opencv.git
synced 2024-11-25 03:30:34 +08:00
Made additional internal header modules/objdetect/src/cascadedetect.hpp, and moved
some internal classes and template functions from cascadedetect.cpp to this header. This will allow to make a child class for such classes as LBPEvaluator, etc. Also made all "private" fields in LBPEvaluator and HaarEvaluator to be "protected".
This commit is contained in:
parent
d87a56a639
commit
dc13ec205d
@ -42,6 +42,8 @@
|
||||
#include "precomp.hpp"
|
||||
#include <cstdio>
|
||||
|
||||
#include "cascadedetect.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
@ -379,60 +381,6 @@ void groupRectangles_meanshift(vector<Rect>& rectList, vector<double>& foundWeig
|
||||
}
|
||||
|
||||
|
||||
#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 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 + w, y) */ \
|
||||
(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)
|
||||
|
||||
FeatureEvaluator::~FeatureEvaluator() {}
|
||||
bool FeatureEvaluator::read(const FileNode&) {return true;}
|
||||
@ -444,101 +392,6 @@ double FeatureEvaluator::calcOrd(int) const { return 0.; }
|
||||
int FeatureEvaluator::calcCat(int) const { return 0; }
|
||||
|
||||
//---------------------------------------------- HaarEvaluator ---------------------------------------
|
||||
class HaarEvaluator : public FeatureEvaluator
|
||||
{
|
||||
public:
|
||||
struct Feature
|
||||
{
|
||||
Feature();
|
||||
|
||||
float calc( int offset ) const;
|
||||
void updatePtrs( const Mat& sum );
|
||||
bool read( const FileNode& node );
|
||||
|
||||
bool tilted;
|
||||
|
||||
enum { RECT_NUM = 3 };
|
||||
|
||||
struct
|
||||
{
|
||||
Rect r;
|
||||
float weight;
|
||||
} rect[RECT_NUM];
|
||||
|
||||
const int* p[RECT_NUM][4];
|
||||
};
|
||||
|
||||
HaarEvaluator();
|
||||
virtual ~HaarEvaluator();
|
||||
|
||||
virtual bool read( const FileNode& node );
|
||||
virtual Ptr<FeatureEvaluator> clone() const;
|
||||
virtual int getFeatureType() const { return FeatureEvaluator::HAAR; }
|
||||
|
||||
virtual bool setImage(const Mat&, Size origWinSize);
|
||||
virtual bool setWindow(Point pt);
|
||||
|
||||
double operator()(int featureIdx) const
|
||||
{ return featuresPtr[featureIdx].calc(offset) * varianceNormFactor; }
|
||||
virtual double calcOrd(int featureIdx) const
|
||||
{ return (*this)(featureIdx); }
|
||||
|
||||
private:
|
||||
Size origWinSize;
|
||||
Ptr<vector<Feature> > features;
|
||||
Feature* featuresPtr; // optimization
|
||||
bool hasTiltedFeatures;
|
||||
|
||||
Mat sum0, sqsum0, tilted0;
|
||||
Mat sum, sqsum, tilted;
|
||||
|
||||
Rect normrect;
|
||||
const int *p[4];
|
||||
const double *pq[4];
|
||||
|
||||
int offset;
|
||||
double 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;
|
||||
p[0][0] = p[0][1] = p[0][2] = p[0][3] =
|
||||
p[1][0] = p[1][1] = p[1][2] = p[1][3] =
|
||||
p[2][0] = p[2][1] = p[2][2] = p[2][3] = 0;
|
||||
}
|
||||
|
||||
inline float HaarEvaluator::Feature :: calc( int offset ) const
|
||||
{
|
||||
float ret = rect[0].weight * CALC_SUM(p[0], offset) + rect[1].weight * CALC_SUM(p[1], offset);
|
||||
|
||||
if( rect[2].weight != 0.0f )
|
||||
ret += rect[2].weight * CALC_SUM(p[2], offset);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline void HaarEvaluator::Feature :: updatePtrs( const Mat& sum )
|
||||
{
|
||||
const int* ptr = (const int*)sum.data;
|
||||
size_t step = sum.step/sizeof(ptr[0]);
|
||||
if (tilted)
|
||||
{
|
||||
CV_TILTED_PTRS( p[0][0], p[0][1], p[0][2], p[0][3], ptr, rect[0].r, step );
|
||||
CV_TILTED_PTRS( p[1][0], p[1][1], p[1][2], p[1][3], ptr, rect[1].r, step );
|
||||
if (rect[2].weight)
|
||||
CV_TILTED_PTRS( p[2][0], p[2][1], p[2][2], p[2][3], ptr, rect[2].r, step );
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_SUM_PTRS( p[0][0], p[0][1], p[0][2], p[0][3], ptr, rect[0].r, step );
|
||||
CV_SUM_PTRS( p[1][0], p[1][1], p[1][2], p[1][3], ptr, rect[1].r, step );
|
||||
if (rect[2].weight)
|
||||
CV_SUM_PTRS( p[2][0], p[2][1], p[2][2], p[2][3], ptr, rect[2].r, step );
|
||||
}
|
||||
}
|
||||
|
||||
bool HaarEvaluator::Feature :: read( const FileNode& node )
|
||||
{
|
||||
@ -670,84 +523,6 @@ bool HaarEvaluator::setWindow( Point pt )
|
||||
}
|
||||
|
||||
//---------------------------------------------- LBPEvaluator -------------------------------------
|
||||
|
||||
class LBPEvaluator : public FeatureEvaluator
|
||||
{
|
||||
public:
|
||||
struct Feature
|
||||
{
|
||||
Feature();
|
||||
Feature( int x, int y, int _block_w, int _block_h ) :
|
||||
rect(x, y, _block_w, _block_h) {}
|
||||
|
||||
int calc( int offset ) const;
|
||||
void updatePtrs( const Mat& sum );
|
||||
bool read(const FileNode& node );
|
||||
|
||||
Rect rect; // weight and height for block
|
||||
const int* p[16]; // fast
|
||||
};
|
||||
|
||||
LBPEvaluator();
|
||||
virtual ~LBPEvaluator();
|
||||
|
||||
virtual bool read( const FileNode& node );
|
||||
virtual Ptr<FeatureEvaluator> clone() const;
|
||||
virtual int getFeatureType() const { return FeatureEvaluator::LBP; }
|
||||
|
||||
virtual bool setImage(const Mat& image, Size _origWinSize);
|
||||
virtual bool setWindow(Point pt);
|
||||
|
||||
int operator()(int featureIdx) const
|
||||
{ return featuresPtr[featureIdx].calc(offset); }
|
||||
virtual int calcCat(int featureIdx) const
|
||||
{ return (*this)(featureIdx); }
|
||||
private:
|
||||
Size origWinSize;
|
||||
Ptr<vector<Feature> > features;
|
||||
Feature* featuresPtr; // optimization
|
||||
Mat sum0, sum;
|
||||
Rect normrect;
|
||||
|
||||
int offset;
|
||||
};
|
||||
|
||||
|
||||
inline LBPEvaluator::Feature :: Feature()
|
||||
{
|
||||
rect = Rect();
|
||||
for( int i = 0; i < 16; i++ )
|
||||
p[i] = 0;
|
||||
}
|
||||
|
||||
inline int LBPEvaluator::Feature :: calc( int offset ) const
|
||||
{
|
||||
int cval = CALC_SUM_( p[5], p[6], p[9], p[10], offset );
|
||||
|
||||
return (CALC_SUM_( p[0], p[1], p[4], p[5], offset ) >= cval ? 128 : 0) | // 0
|
||||
(CALC_SUM_( p[1], p[2], p[5], p[6], offset ) >= cval ? 64 : 0) | // 1
|
||||
(CALC_SUM_( p[2], p[3], p[6], p[7], offset ) >= cval ? 32 : 0) | // 2
|
||||
(CALC_SUM_( p[6], p[7], p[10], p[11], offset ) >= cval ? 16 : 0) | // 5
|
||||
(CALC_SUM_( p[10], p[11], p[14], p[15], offset ) >= cval ? 8 : 0)| // 8
|
||||
(CALC_SUM_( p[9], p[10], p[13], p[14], offset ) >= cval ? 4 : 0)| // 7
|
||||
(CALC_SUM_( p[8], p[9], p[12], p[13], offset ) >= cval ? 2 : 0)| // 6
|
||||
(CALC_SUM_( p[4], p[5], p[8], p[9], offset ) >= cval ? 1 : 0);
|
||||
}
|
||||
|
||||
inline void LBPEvaluator::Feature :: updatePtrs( const Mat& sum )
|
||||
{
|
||||
const int* ptr = (const int*)sum.data;
|
||||
size_t step = sum.step/sizeof(ptr[0]);
|
||||
Rect tr = rect;
|
||||
CV_SUM_PTRS( p[0], p[1], p[4], p[5], ptr, tr, step );
|
||||
tr.x += 2*rect.width;
|
||||
CV_SUM_PTRS( p[2], p[3], p[6], p[7], ptr, tr, step );
|
||||
tr.y += 2*rect.height;
|
||||
CV_SUM_PTRS( p[10], p[11], p[14], p[15], ptr, tr, step );
|
||||
tr.x -= 2*rect.width;
|
||||
CV_SUM_PTRS( p[8], p[9], p[12], p[13], ptr, tr, step );
|
||||
}
|
||||
|
||||
bool LBPEvaluator::Feature :: read(const FileNode& node )
|
||||
{
|
||||
FileNode rnode = node[CC_RECT];
|
||||
@ -862,171 +637,6 @@ bool CascadeClassifier::load(const string& filename)
|
||||
return !oldCascade.empty();
|
||||
}
|
||||
|
||||
template<class FEval>
|
||||
inline int predictOrdered( CascadeClassifier& cascade, Ptr<FeatureEvaluator> &_featureEvaluator, double& sum )
|
||||
{
|
||||
int nstages = (int)cascade.data.stages.size();
|
||||
int nodeOfs = 0, leafOfs = 0;
|
||||
FEval& featureEvaluator = (FEval&)*_featureEvaluator;
|
||||
float* cascadeLeaves = &cascade.data.leaves[0];
|
||||
CascadeClassifier::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0];
|
||||
CascadeClassifier::Data::DTree* cascadeWeaks = &cascade.data.classifiers[0];
|
||||
CascadeClassifier::Data::Stage* cascadeStages = &cascade.data.stages[0];
|
||||
|
||||
for( int si = 0; si < nstages; si++ )
|
||||
{
|
||||
CascadeClassifier::Data::Stage& stage = cascadeStages[si];
|
||||
int wi, ntrees = stage.ntrees;
|
||||
sum = 0;
|
||||
|
||||
for( wi = 0; wi < ntrees; wi++ )
|
||||
{
|
||||
CascadeClassifier::Data::DTree& weak = cascadeWeaks[stage.first + wi];
|
||||
int idx = 0, root = nodeOfs;
|
||||
|
||||
do
|
||||
{
|
||||
CascadeClassifier::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( CascadeClassifier& cascade, Ptr<FeatureEvaluator> &_featureEvaluator, double& sum )
|
||||
{
|
||||
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];
|
||||
CascadeClassifier::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0];
|
||||
CascadeClassifier::Data::DTree* cascadeWeaks = &cascade.data.classifiers[0];
|
||||
CascadeClassifier::Data::Stage* cascadeStages = &cascade.data.stages[0];
|
||||
|
||||
for(int si = 0; si < nstages; si++ )
|
||||
{
|
||||
CascadeClassifier::Data::Stage& stage = cascadeStages[si];
|
||||
int wi, ntrees = stage.ntrees;
|
||||
sum = 0;
|
||||
|
||||
for( wi = 0; wi < ntrees; wi++ )
|
||||
{
|
||||
CascadeClassifier::Data::DTree& weak = cascadeWeaks[stage.first + wi];
|
||||
int idx = 0, root = nodeOfs;
|
||||
do
|
||||
{
|
||||
CascadeClassifier::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( CascadeClassifier& cascade, Ptr<FeatureEvaluator> &_featureEvaluator, double& sum )
|
||||
{
|
||||
int nodeOfs = 0, leafOfs = 0;
|
||||
FEval& featureEvaluator = (FEval&)*_featureEvaluator;
|
||||
float* cascadeLeaves = &cascade.data.leaves[0];
|
||||
CascadeClassifier::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0];
|
||||
CascadeClassifier::Data::Stage* cascadeStages = &cascade.data.stages[0];
|
||||
|
||||
int nstages = (int)cascade.data.stages.size();
|
||||
for( int stageIdx = 0; stageIdx < nstages; stageIdx++ )
|
||||
{
|
||||
CascadeClassifier::Data::Stage& stage = cascadeStages[stageIdx];
|
||||
sum = 0.0;
|
||||
|
||||
int ntrees = stage.ntrees;
|
||||
for( int i = 0; i < ntrees; i++, nodeOfs++, leafOfs+= 2 )
|
||||
{
|
||||
CascadeClassifier::Data::DTreeNode& node = cascadeNodes[nodeOfs];
|
||||
double value = featureEvaluator(node.featureIdx);
|
||||
sum += cascadeLeaves[ value < node.threshold ? leafOfs : leafOfs + 1 ];
|
||||
}
|
||||
|
||||
if( sum < stage.threshold )
|
||||
return -stageIdx;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<class FEval>
|
||||
inline int predictCategoricalStump( CascadeClassifier& cascade, Ptr<FeatureEvaluator> &_featureEvaluator, double& sum )
|
||||
{
|
||||
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];
|
||||
CascadeClassifier::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0];
|
||||
CascadeClassifier::Data::Stage* cascadeStages = &cascade.data.stages[0];
|
||||
|
||||
#ifdef HAVE_TEGRA_OPTIMIZATION
|
||||
float tmp; // float accumulator -- float operations are quicker
|
||||
#endif
|
||||
for( int si = 0; si < nstages; si++ )
|
||||
{
|
||||
CascadeClassifier::Data::Stage& stage = cascadeStages[si];
|
||||
int wi, ntrees = stage.ntrees;
|
||||
#ifdef HAVE_TEGRA_OPTIMIZATION
|
||||
tmp = 0;
|
||||
#else
|
||||
sum = 0;
|
||||
#endif
|
||||
|
||||
for( wi = 0; wi < ntrees; wi++ )
|
||||
{
|
||||
CascadeClassifier::Data::DTreeNode& node = cascadeNodes[nodeOfs];
|
||||
int c = featureEvaluator(node.featureIdx);
|
||||
const int* subset = &cascadeSubsets[nodeOfs*subsetSize];
|
||||
#ifdef HAVE_TEGRA_OPTIMIZATION
|
||||
tmp += cascadeLeaves[ subset[c>>5] & (1 << (c & 31)) ? leafOfs : leafOfs+1];
|
||||
#else
|
||||
sum += cascadeLeaves[ subset[c>>5] & (1 << (c & 31)) ? leafOfs : leafOfs+1];
|
||||
#endif
|
||||
nodeOfs++;
|
||||
leafOfs += 2;
|
||||
}
|
||||
#ifdef HAVE_TEGRA_OPTIMIZATION
|
||||
if( tmp < stage.threshold ) {
|
||||
sum = (double)tmp;
|
||||
return -si;
|
||||
}
|
||||
#else
|
||||
if( sum < stage.threshold )
|
||||
return -si;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_TEGRA_OPTIMIZATION
|
||||
sum = (double)tmp;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CascadeClassifier::runAt( Ptr<FeatureEvaluator>& featureEvaluator, Point pt, double& weight )
|
||||
{
|
||||
|
410
modules/objdetect/src/cascadedetect.hpp
Normal file
410
modules/objdetect/src/cascadedetect.hpp
Normal file
@ -0,0 +1,410 @@
|
||||
#pragma once
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
#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 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 + w, y) */ \
|
||||
(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)
|
||||
|
||||
|
||||
//---------------------------------------------- HaarEvaluator ---------------------------------------
|
||||
class HaarEvaluator : public FeatureEvaluator
|
||||
{
|
||||
public:
|
||||
struct Feature
|
||||
{
|
||||
Feature();
|
||||
|
||||
float calc( int offset ) const;
|
||||
void updatePtrs( const Mat& sum );
|
||||
bool read( const FileNode& node );
|
||||
|
||||
bool tilted;
|
||||
|
||||
enum { RECT_NUM = 3 };
|
||||
|
||||
struct
|
||||
{
|
||||
Rect r;
|
||||
float weight;
|
||||
} rect[RECT_NUM];
|
||||
|
||||
const int* p[RECT_NUM][4];
|
||||
};
|
||||
|
||||
HaarEvaluator();
|
||||
virtual ~HaarEvaluator();
|
||||
|
||||
virtual bool read( const FileNode& node );
|
||||
virtual Ptr<FeatureEvaluator> clone() const;
|
||||
virtual int getFeatureType() const { return FeatureEvaluator::HAAR; }
|
||||
|
||||
virtual bool setImage(const Mat&, Size origWinSize);
|
||||
virtual bool setWindow(Point pt);
|
||||
|
||||
double operator()(int featureIdx) const
|
||||
{ return featuresPtr[featureIdx].calc(offset) * varianceNormFactor; }
|
||||
virtual double calcOrd(int featureIdx) const
|
||||
{ return (*this)(featureIdx); }
|
||||
|
||||
protected:
|
||||
Size origWinSize;
|
||||
Ptr<vector<Feature> > features;
|
||||
Feature* featuresPtr; // optimization
|
||||
bool hasTiltedFeatures;
|
||||
|
||||
Mat sum0, sqsum0, tilted0;
|
||||
Mat sum, sqsum, tilted;
|
||||
|
||||
Rect normrect;
|
||||
const int *p[4];
|
||||
const double *pq[4];
|
||||
|
||||
int offset;
|
||||
double 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;
|
||||
p[0][0] = p[0][1] = p[0][2] = p[0][3] =
|
||||
p[1][0] = p[1][1] = p[1][2] = p[1][3] =
|
||||
p[2][0] = p[2][1] = p[2][2] = p[2][3] = 0;
|
||||
}
|
||||
|
||||
inline float HaarEvaluator::Feature :: calc( int offset ) const
|
||||
{
|
||||
float ret = rect[0].weight * CALC_SUM(p[0], offset) + rect[1].weight * CALC_SUM(p[1], offset);
|
||||
|
||||
if( rect[2].weight != 0.0f )
|
||||
ret += rect[2].weight * CALC_SUM(p[2], offset);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline void HaarEvaluator::Feature :: updatePtrs( const Mat& sum )
|
||||
{
|
||||
const int* ptr = (const int*)sum.data;
|
||||
size_t step = sum.step/sizeof(ptr[0]);
|
||||
if (tilted)
|
||||
{
|
||||
CV_TILTED_PTRS( p[0][0], p[0][1], p[0][2], p[0][3], ptr, rect[0].r, step );
|
||||
CV_TILTED_PTRS( p[1][0], p[1][1], p[1][2], p[1][3], ptr, rect[1].r, step );
|
||||
if (rect[2].weight)
|
||||
CV_TILTED_PTRS( p[2][0], p[2][1], p[2][2], p[2][3], ptr, rect[2].r, step );
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_SUM_PTRS( p[0][0], p[0][1], p[0][2], p[0][3], ptr, rect[0].r, step );
|
||||
CV_SUM_PTRS( p[1][0], p[1][1], p[1][2], p[1][3], ptr, rect[1].r, step );
|
||||
if (rect[2].weight)
|
||||
CV_SUM_PTRS( p[2][0], p[2][1], p[2][2], p[2][3], ptr, rect[2].r, step );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------- LBPEvaluator -------------------------------------
|
||||
|
||||
class LBPEvaluator : public FeatureEvaluator
|
||||
{
|
||||
public:
|
||||
struct Feature
|
||||
{
|
||||
Feature();
|
||||
Feature( int x, int y, int _block_w, int _block_h ) :
|
||||
rect(x, y, _block_w, _block_h) {}
|
||||
|
||||
int calc( int offset ) const;
|
||||
void updatePtrs( const Mat& sum );
|
||||
bool read(const FileNode& node );
|
||||
|
||||
Rect rect; // weight and height for block
|
||||
const int* p[16]; // fast
|
||||
};
|
||||
|
||||
LBPEvaluator();
|
||||
virtual ~LBPEvaluator();
|
||||
|
||||
virtual bool read( const FileNode& node );
|
||||
virtual Ptr<FeatureEvaluator> clone() const;
|
||||
virtual int getFeatureType() const { return FeatureEvaluator::LBP; }
|
||||
|
||||
virtual bool setImage(const Mat& image, Size _origWinSize);
|
||||
virtual bool setWindow(Point pt);
|
||||
|
||||
int operator()(int featureIdx) const
|
||||
{ return featuresPtr[featureIdx].calc(offset); }
|
||||
virtual int calcCat(int featureIdx) const
|
||||
{ return (*this)(featureIdx); }
|
||||
protected:
|
||||
Size origWinSize;
|
||||
Ptr<vector<Feature> > features;
|
||||
Feature* featuresPtr; // optimization
|
||||
Mat sum0, sum;
|
||||
Rect normrect;
|
||||
|
||||
int offset;
|
||||
};
|
||||
|
||||
|
||||
inline LBPEvaluator::Feature :: Feature()
|
||||
{
|
||||
rect = Rect();
|
||||
for( int i = 0; i < 16; i++ )
|
||||
p[i] = 0;
|
||||
}
|
||||
|
||||
inline int LBPEvaluator::Feature :: calc( int offset ) const
|
||||
{
|
||||
int cval = CALC_SUM_( p[5], p[6], p[9], p[10], offset );
|
||||
|
||||
return (CALC_SUM_( p[0], p[1], p[4], p[5], offset ) >= cval ? 128 : 0) | // 0
|
||||
(CALC_SUM_( p[1], p[2], p[5], p[6], offset ) >= cval ? 64 : 0) | // 1
|
||||
(CALC_SUM_( p[2], p[3], p[6], p[7], offset ) >= cval ? 32 : 0) | // 2
|
||||
(CALC_SUM_( p[6], p[7], p[10], p[11], offset ) >= cval ? 16 : 0) | // 5
|
||||
(CALC_SUM_( p[10], p[11], p[14], p[15], offset ) >= cval ? 8 : 0)| // 8
|
||||
(CALC_SUM_( p[9], p[10], p[13], p[14], offset ) >= cval ? 4 : 0)| // 7
|
||||
(CALC_SUM_( p[8], p[9], p[12], p[13], offset ) >= cval ? 2 : 0)| // 6
|
||||
(CALC_SUM_( p[4], p[5], p[8], p[9], offset ) >= cval ? 1 : 0);
|
||||
}
|
||||
|
||||
inline void LBPEvaluator::Feature :: updatePtrs( const Mat& sum )
|
||||
{
|
||||
const int* ptr = (const int*)sum.data;
|
||||
size_t step = sum.step/sizeof(ptr[0]);
|
||||
Rect tr = rect;
|
||||
CV_SUM_PTRS( p[0], p[1], p[4], p[5], ptr, tr, step );
|
||||
tr.x += 2*rect.width;
|
||||
CV_SUM_PTRS( p[2], p[3], p[6], p[7], ptr, tr, step );
|
||||
tr.y += 2*rect.height;
|
||||
CV_SUM_PTRS( p[10], p[11], p[14], p[15], ptr, tr, step );
|
||||
tr.x -= 2*rect.width;
|
||||
CV_SUM_PTRS( p[8], p[9], p[12], p[13], ptr, tr, step );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------- predictor functions -------------------------------------
|
||||
|
||||
template<class FEval>
|
||||
inline int predictOrdered( CascadeClassifier& cascade, Ptr<FeatureEvaluator> &_featureEvaluator, double& sum )
|
||||
{
|
||||
int nstages = (int)cascade.data.stages.size();
|
||||
int nodeOfs = 0, leafOfs = 0;
|
||||
FEval& featureEvaluator = (FEval&)*_featureEvaluator;
|
||||
float* cascadeLeaves = &cascade.data.leaves[0];
|
||||
CascadeClassifier::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0];
|
||||
CascadeClassifier::Data::DTree* cascadeWeaks = &cascade.data.classifiers[0];
|
||||
CascadeClassifier::Data::Stage* cascadeStages = &cascade.data.stages[0];
|
||||
|
||||
for( int si = 0; si < nstages; si++ )
|
||||
{
|
||||
CascadeClassifier::Data::Stage& stage = cascadeStages[si];
|
||||
int wi, ntrees = stage.ntrees;
|
||||
sum = 0;
|
||||
|
||||
for( wi = 0; wi < ntrees; wi++ )
|
||||
{
|
||||
CascadeClassifier::Data::DTree& weak = cascadeWeaks[stage.first + wi];
|
||||
int idx = 0, root = nodeOfs;
|
||||
|
||||
do
|
||||
{
|
||||
CascadeClassifier::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( CascadeClassifier& cascade, Ptr<FeatureEvaluator> &_featureEvaluator, double& sum )
|
||||
{
|
||||
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];
|
||||
CascadeClassifier::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0];
|
||||
CascadeClassifier::Data::DTree* cascadeWeaks = &cascade.data.classifiers[0];
|
||||
CascadeClassifier::Data::Stage* cascadeStages = &cascade.data.stages[0];
|
||||
|
||||
for(int si = 0; si < nstages; si++ )
|
||||
{
|
||||
CascadeClassifier::Data::Stage& stage = cascadeStages[si];
|
||||
int wi, ntrees = stage.ntrees;
|
||||
sum = 0;
|
||||
|
||||
for( wi = 0; wi < ntrees; wi++ )
|
||||
{
|
||||
CascadeClassifier::Data::DTree& weak = cascadeWeaks[stage.first + wi];
|
||||
int idx = 0, root = nodeOfs;
|
||||
do
|
||||
{
|
||||
CascadeClassifier::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( CascadeClassifier& cascade, Ptr<FeatureEvaluator> &_featureEvaluator, double& sum )
|
||||
{
|
||||
int nodeOfs = 0, leafOfs = 0;
|
||||
FEval& featureEvaluator = (FEval&)*_featureEvaluator;
|
||||
float* cascadeLeaves = &cascade.data.leaves[0];
|
||||
CascadeClassifier::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0];
|
||||
CascadeClassifier::Data::Stage* cascadeStages = &cascade.data.stages[0];
|
||||
|
||||
int nstages = (int)cascade.data.stages.size();
|
||||
for( int stageIdx = 0; stageIdx < nstages; stageIdx++ )
|
||||
{
|
||||
CascadeClassifier::Data::Stage& stage = cascadeStages[stageIdx];
|
||||
sum = 0.0;
|
||||
|
||||
int ntrees = stage.ntrees;
|
||||
for( int i = 0; i < ntrees; i++, nodeOfs++, leafOfs+= 2 )
|
||||
{
|
||||
CascadeClassifier::Data::DTreeNode& node = cascadeNodes[nodeOfs];
|
||||
double value = featureEvaluator(node.featureIdx);
|
||||
sum += cascadeLeaves[ value < node.threshold ? leafOfs : leafOfs + 1 ];
|
||||
}
|
||||
|
||||
if( sum < stage.threshold )
|
||||
return -stageIdx;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<class FEval>
|
||||
inline int predictCategoricalStump( CascadeClassifier& cascade, Ptr<FeatureEvaluator> &_featureEvaluator, double& sum )
|
||||
{
|
||||
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];
|
||||
CascadeClassifier::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0];
|
||||
CascadeClassifier::Data::Stage* cascadeStages = &cascade.data.stages[0];
|
||||
|
||||
#ifdef HAVE_TEGRA_OPTIMIZATION
|
||||
float tmp; // float accumulator -- float operations are quicker
|
||||
#endif
|
||||
for( int si = 0; si < nstages; si++ )
|
||||
{
|
||||
CascadeClassifier::Data::Stage& stage = cascadeStages[si];
|
||||
int wi, ntrees = stage.ntrees;
|
||||
#ifdef HAVE_TEGRA_OPTIMIZATION
|
||||
tmp = 0;
|
||||
#else
|
||||
sum = 0;
|
||||
#endif
|
||||
|
||||
for( wi = 0; wi < ntrees; wi++ )
|
||||
{
|
||||
CascadeClassifier::Data::DTreeNode& node = cascadeNodes[nodeOfs];
|
||||
int c = featureEvaluator(node.featureIdx);
|
||||
const int* subset = &cascadeSubsets[nodeOfs*subsetSize];
|
||||
#ifdef HAVE_TEGRA_OPTIMIZATION
|
||||
tmp += cascadeLeaves[ subset[c>>5] & (1 << (c & 31)) ? leafOfs : leafOfs+1];
|
||||
#else
|
||||
sum += cascadeLeaves[ subset[c>>5] & (1 << (c & 31)) ? leafOfs : leafOfs+1];
|
||||
#endif
|
||||
nodeOfs++;
|
||||
leafOfs += 2;
|
||||
}
|
||||
#ifdef HAVE_TEGRA_OPTIMIZATION
|
||||
if( tmp < stage.threshold ) {
|
||||
sum = (double)tmp;
|
||||
return -si;
|
||||
}
|
||||
#else
|
||||
if( sum < stage.threshold )
|
||||
return -si;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_TEGRA_OPTIMIZATION
|
||||
sum = (double)tmp;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user