赞
踩
原地址:http://blog.csdn.net/delltdk/article/details/9186875
在进入detectMultiScal函数之前,首先需要对CascadeClassifier做初始化。
1. 初始化——read函数
CascadeClassifier的初始化很简单:
cv::CascadeClassifier classifier;
classifier.load(“cascade.xml”); //这里的xml是训练得到的分类器xml
CascadeClassifier类中既有load也有read函数,二者是相同的,load将引用read函数。
1.1 xml的结构
训练得到的分类器以xml形式保存,整体上它包括stageType、featureType、height、width、stageParams、featureParams、stages、features几个节点。
图1. 分类器的Xml文件整体结构
除stages和features外,其他主要是一些分类器的参数。
Stages中包含15个stage(训练程序设定),每个stage中包含多个weakClassifiers,而每个weakClassifier中又包含一个internalNodes和一个leafValues。internalNodes中四个变量代表一个node,分别为node中的left/right标记、特征池中的ID和threshold。leafValues中两个变量代表一个node,分别为left leaf的值和right leaf的值。
图2. 分类器的Xml文件具体结构
而features是分类器的特征池,每个特征包含一个矩形和要提取的特征序号(0~35)。
图3. features的具体结构
1.2 read的过程
下面是read代码,主要包括从xml中获取两部分内容:data和featureEvaluator的读取。
bool CascadeClassifier::read(constFileNode&root)
{
if( !data.read(root) )//data成员变量的读取
return false;
// load features---特征的读取
featureEvaluator= FeatureEvaluator::create(data.featureType);
FileNodefn =root[CC_FEATURES];
if( fn.empty() )
return false;
return featureEvaluator->read(fn);
}
1.2.1 data成员变量的读取
data的读取中同样可以分为两部分:分类器参数读取和stage分类树的建立。
首先是参数部分的获取。
static constfloatTHRESHOLD_EPS= 1e-5f;
// load stage params
// stageType为BOOST类型
string stageTypeStr = (string)root[CC_STAGE_TYPE];
if( stageTypeStr == CC_BOOST)
stageType= BOOST;
else
return false;
//这里以HOG特征分类器为例,featureType=2(HOG)
string featureTypeStr = (string)root[CC_FEATURE_TYPE];
if( featureTypeStr == CC_HAAR)
featureType= FeatureEvaluator::HAAR;
else if( featureTypeStr== CC_LBP )
featureType= FeatureEvaluator::LBP;
else if( featureTypeStr== CC_HOG )
featureType= FeatureEvaluator::HOG;
else
return false;
//检测窗口的最小size,也就是正样本的size
origWinSize.width = (int)root[CC_WIDTH];
origWinSize.height = (int)root[CC_HEIGHT];
CV_Assert(origWinSize.height> 0 &&origWinSize.width > 0 );
//我训练得到的HOG分类器为true,还不清楚这里的意思
isStumpBased= (int)(root[CC_STAGE_PARAMS][CC_MAX_DEPTH])== 1 ?true : false;
// load feature params
//载入特征参数,HOG分类器下包括两个参数:maxCatCount和featSize,featSize很透明,就是特征的种类数,这里为36,是指每个block中4个cell、每个cell9个梯度方向的直方图。例如特征号为3时,计算的是当前窗口中划分为4个cell后第一个cell中所有点在120°方向(可能是,这要视起始角度而定)上分量的和,然后经过归一化后的值。对于第二个参数maxCatCount,这里为0,尚不清楚(这是指代表一个弱分类器的树的类别数量,用来计算一棵树的节点大小也就是nodeStep)
FileNode fn = root[CC_FEATURE_PARAMS];
if( fn.empty() )
return false;
ncategories= fn[CC_MAX_CAT_COUNT];
int subsetSize = (ncategories+ 31)/32,
nodeStep = 3 + ( ncategories>0 ? subsetSize: 1 );
至此分类器参数读取完毕。
接下来是建立分类树,也就是stage部分的载入。
// load stages
fn = root[CC_STAGES];
if( fn.empty() )
return false;
stages.reserve(fn.size());//stages包含15个节点,fn.size()==15
classifiers.clear();
nodes.clear();
FileNodeIteratorit =fn.begin(),it_end=fn.end();
for( int si = 0; it != it_end; si++, ++it )//遍历stages
{
FileNodefns = *it;
Stagestage;//stage结构中包含threshold、ntrees和first三个变量
stage.threshold = (float)fns[CC_STAGE_THRESHOLD]-THRESHOLD_EPS;
fns= fns[CC_WEAK_CLASSIFIERS];
if(fns.empty())
returnfalse;
stage.ntrees = (int)fns.size();
stage.first = (int)classifiers.size();//ntrees和first指出该stage中包含的树的数目和起始位置
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。