OpenCV的级联分类器分为两部分,训练与检测。训练那块代码在apps目录下,有旧分类器haartraining和新分类器traincascade各自的代码。目前没去看,训练用OpenCV给的程序目前就足够了。
检测这块代码在以下3个文件中
E:\opencv\sources\modules\objdetect\include\opencv2\objdetect\objdetect.hpp;
定义了旧分类器计算Haar特征值的结构体:
CvHaarFeature(Haar特征结构体),
CvHaarClassifier(Haar特征分类器结构体),
CvHaarStageClassifier(Haar强分类器结构体),
CvHaarClassifierCascade(Haar强分类器级联结构体)
定义了类:
FeatureEvaluator(特征值计算类,新分类器使用),
CascadeClassifier(级联分类器)类
E:\opencv\sources\modules\objdetect\src\cascadedetect.hpp
定义了类,以下几个类都是继承自FeatureEvaluator:
HaarEvaluator(Haar特征值计算类),
LBPEvaluator(LBP特征值计算类),
HOGEvaluator(HOG特征值计算类)
定义了函数:
predictOrdered(计算并验证是否通过级联强分类器)
predictCategorical
predictOrderedStump
predictCategoricalStump
E:\opencv\sources\modules\objdetect\src\cascadedetect.cpp
检测时首先调用CascadeClassifier::load(const string& filename)函数载入分类器xml文件,如果是旧分类器,将xml中的信息读取到Ptr<CvHaarClassifierCascade> oldCascade保护变量中,否则读入到强级联分类器数据类对象Data中,根据特征创建对应的特征计算类,得到指针Ptr<FeatureEvaluator> featureEvaluator的值,Data对象定义如下
//CascadeClassifier的Protected保护子类
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; //在classifier中的起始位置
int ntrees; //该强分类器中的弱分类器数
float threshold; //强分类器阈值
};
bool read(const FileNode &node); //读取强分类器
bool isStumpBased; //是否只有树桩
int stageType; //BOOST,boostType:GAB、RAB等
int featureType; //HAAR、HOG、LBP
int ncategories; //maxCatCount,LBP为256,其余为0
Size origWinSize;
vector<Stage> stages;
vector<DTree> classifiers;
vector<DTreeNode> nodes;
vector<float> leaves;
vector<int> subsets;
};
Data data; //CascadeClassifier的保护子类对象成员,存放强级联分类器数据。
CascadeClassifier有两个多尺度检测函数的实现(如下),读取xml后可以调用这两个函数进行级联强分类器检测(使用不同的xml就是不同的检测,如人脸检测,眼睛,鼻子,嘴巴等检测)
CV_WRAP virtual void detectMultiScale( const Mat& image,//图像,
CV_OUT vector<Rect>& objects,//输出矩形框
double scaleFactor=1.1, //缩放比例,必须大于1
int minNeighbors=3 ,//合并窗口最小间距,每个候选矩阵至少需要包含的附近元素个数(一个目标至少要检测多少次)
int flags=0, //检测标记,只对旧格式分类器有效,CV_HAAR_DO_CANNY_PRUNING(canny边缘检测)
| CV_HAAR_SCALE_IMAGE(缩放图像,旧分类器必须选这个)
|CV_HAAR_FIND_BIGGEST_OBJECT(寻找最大目标)
|CV_HAAR_DO_ROUGH_SEARCH(做粗略搜索) **如果寻找最大目标就不能缩放图像和canny检测。
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,//未通过的那个强分类器CART树叶子节点值累加和(小于该强分类器阈值)
double scaleFactor=1.1,
int minNeighbors=3, int flags=0,
Size minSize=Size(),
</