最近在看opencv中adaboost的源码的时候,发现在实现文件..\OpenCV2.0\apps\traincascade\cascadeclassifier.cpp中的一个问题:
(1)CvCascadeClassifier类的成员函数train函数中有这么一句:
此句代码的本意是用传入的命令行参数_posFilename、_negFilename和_cascadeParams初始化imgReader对象(用于读取图像进行训练的CvCascadeImageReader类)
(2)这里的_cascadeParams是CvCascadeParams类的对象,属于CvCascadeClassifier类的私有对象,主要保存的是级联参数:
-stageType <BOOST(default)>:级别(stage)参数。目前只支持将BOOST分类器作为级联的类型;
-featureType<{HAAR(default), LBP}>:特征的类型: HAAR - 类Haar特征; LBP - 局部纹理模式特征(默认Harr);
-w <sampleWidth>:训练样本的宽(单位为像素,默认24);
-h <sampleHeight>:训练样本的高(单位为像素,默认24);
训练样本的尺寸必须跟训练样本创建(使用 opencv_createsamples 程序创建)时的尺寸保持一致。
(3)其中_cascadeParams的一个成员winSize保存的就是-w和-h参数。但是这里实际使用的是CvCascadeClassifier类的成员cascadeParams(注意没有下划线),而这个cascadeParams是由CvCascadeParams类的默认构造函数创建的:
看看CvCascadeParams类的默认构造函数吧:
其中winSize是默认大小24*24。
(4)train这一句代码后面的代码才是真正的用传入的参数来对CvCascadeClassifier类中用作参数的成员(主要是cascadeParams,featureParams和stageParams)进行赋值:
(5)那么上面(1)中所说的这一句代码造成什么结果?我们看一下:
首先CvCascadeImageReader类的create函数定义如下:
此时传入参数_winSize为24*24,使得negReader对象的成员winSize被赋值为24*24。而在我们调用CvCascadeClassifier::updateTrainingSet去不断取训练样本的时候会调用CvCascadeClassifier::fillPassedSamples函数,该函数中有这么一句:
当使用getNeg获取负样本的时候,就会调用NegReader::get函数:
传入的_img尺寸为命令行指定的训练样本尺寸,但是winSize成员的大小一直为24*24。假如指定的样本尺寸不是24*24,就会报错:
这也是我之前纠结了好久的一个地方。
(6)opencv2.1及更高版本都修正了这个问题,可以放心使用:
参考我的另一篇博文:Adaboost应用系列之二:Opencv2.0中利用Adaboost训练LBP特征产生xml分类器