一、参考OpenCV的CascadeClassifier类LBPEvaluator类
如下,筛选出存放分类器相关信息的成员变量:
class CV_EXPORTS_W CascadeClassifier { public: CV_WRAP CascadeClassifier(); CV_WRAP CascadeClassifier( const string& filename ); virtual ~CascadeClassifier(); CV_WRAP virtual bool empty() const; CV_WRAP bool load( const string& filename ); virtual bool read( const FileNode& node ); CV_WRAP virtual void detectMultiScale( const Mat& image, CV_OUT vector<Rect>& objects, double scaleFactor=1.1, int minNeighbors=3, int flags=0, Size minSize=Size(), Size maxSize=Size() ); CV_WRAP virtual void detectMultiScale( const Mat& image, CV_OUT vector<Rect>& objects, vector<int>& rejectLevels, vector<double>& levelWeights, double scaleFactor=1.1, int minNeighbors=3, int flags=0, Size minSize=Size(), Size maxSize=Size(), bool outputRejectLevels=false ); bool isOldFormatCascade() const; virtual Size getOriginalWindowSize() const; int getFeatureType() const; bool setImage( const Mat& ); protected: //virtual bool detectSingleScale( const Mat& image, int stripCount, Size processingRectSize, // int stripSize, int yStep, double factor, vector<Rect>& candidates ); virtual bool detectSingleScale( const Mat& image, int stripCount, Size processingRectSize, int stripSize, int yStep, double factor, vector<Rect>& candidates, vector<int>& rejectLevels, vector<double>& levelWeights, bool outputRejectLevels=false); protected: enum { BOOST = 0 }; enum { DO_CANNY_PRUNING = 1, SCALE_IMAGE = 2, FIND_BIGGEST_OBJECT = 4, DO_ROUGH_SEARCH = 8 }; friend class CascadeClassifierInvoker; template<class FEval> friend int predictOrdered( CascadeClassifier& cascade, Ptr<FeatureEvaluator> &featureEvaluator, double& weight); template<class FEval> friend int predictCategorical( CascadeClassifier& cascade, Ptr<FeatureEvaluator> &featureEvaluator, double& weight); template<class FEval> friend int predictOrderedStump( CascadeClassifier& cascade, Ptr<FeatureEvaluator> &featureEvaluator, double& weight); template<class FEval> friend int predictCategoricalStump( CascadeClassifier& cascade, Ptr<FeatureEvaluator> &featureEvaluator, double& weight); bool setImage( Ptr<FeatureEvaluator>& feval, const Mat& image); virtual int runAt( Ptr<FeatureEvaluator>& feval, Point pt, double& weight ); class Data { public: struct CV_EXPORTS DTreeNode { int featureIdx; float threshold; // for ordered features only int left; int right; }; struct CV_EXPORTS DTree { int nodeCount; }; struct CV_EXPORTS Stage { int first; int ntrees; float threshold; }; bool read(const FileNode &node); bool isStumpBased; int stageType; int featureType; int ncategories; Size origWinSize; vector<Stage> stages; vector<DTree> classifiers; vector<DTreeNode> nodes; vector<float> leaves; vector<int> subsets; }; Data data; Ptr<FeatureEvaluator> featureEvaluator; Ptr<CvHaarClassifierCascade> oldCascade; public: class CV_EXPORTS MaskGenerator { public: virtual ~MaskGenerator() {} virtual cv::Mat generateMask(const cv::Mat& src)=0; virtual void initializeMask(const cv::Mat& /*src*/) {}; }; void setMaskGenerator(Ptr<MaskGenerator> maskGenerator); Ptr<MaskGenerator> getMaskGenerator(); void setFaceDetectionMaskGenerator(); protected: Ptr<MaskGenerator> maskGenerator; }; 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; };
二、开始设计适合自己分类器的数据结构
如下图,因为我们打算使用数组方式存储信息,为避免溢出,首先了解自己分类器的强分类器级数,nodes,leaves等信息,由于我们的分类器是通过opencv训练的,所以可以直接Debug查看分类器信息,或者通过xml文件查看。
设计结构体如下:
#ifndef _CP_ADABOOST_ #define _CP_ADABOOST_ #ifdef __cplusplus extern "C"{ #endif typedef struct tagCpSize { int iWidth; int iHeight; }CP_SIZE_S; typedef struct tagCPDTreeNode { int featureIdx; float threshold; // for ordered features only int left; int right; }CP_DTREE_NODE_S; typedef struct tagCpDTree { int nodeCount; }CP_DTREE_S; typedef struct tagCpStage { int first; int ntrees; float threshold; }CP_STAGE_S; typedef struct tagCPRect { int x; int y; int width; int height; }CP_RECT_S; typedef struct tagLBPFeature { CP_RECT_S rect;/*特征位置*/ int* p[16];/* 特征在积分图中的地址 */ }CP_LBP_FEATURE_S; typedef struct tagCpClassifier { bool isStumpBased; int stageType; int featureType; int ncategories; CP_SIZE_S origWinSize; CP_STAGE_S stages[50]; /*强分类器级数*/ int stagerNum;
CP_DTREE_S classifiers[500];
int classfierNum; CP_DTREE_NODE_S nodes[500];
int nodeNum; CP_LBP_FEATURE_S feature[500];
int featureNum; float leaves[1000];
int leaveNum; int subsets[5000];
int subsetNum; }CP_CLASSIFIER_S; #ifdef __cplusplus } #endif #endif /* _CP_ADABOOST_ */