赞
踩
注:部分内容转载自http://blog.csdn.net/delltdk/article/details/9186875
一、简介
在Opencv2.4.9的源码中,对modules模块opencv_objdetect子项目中CascadeClasssifier类中的detectMultiScale函数进行了分析,涉及代码在cascadedetect.hpp和cascadedetect.cpp中。
CascadeClassifier为级联分类器检测类,使用Adaboost的方法,提取LBP\HOG\HAAR特征进行目标检测,加载traincascade进行训练的分类器。
detectMultiScale能够实现多尺度检测,但多尺度检测是通过缩放图像来完成的。
二、函数简介
voidCascadeClassifier::detectMultiScale( const Mat& image, —Mat类型的图像
vector<Rect>& objects,—检测得到的矩形
doublescaleFactor, —图像缩放因子,必须大于1
intminNeighbors,—构成检测目标的相邻矩形的最小个数
int flags, —旧分类器使用,新分类器弃用
Size minObjectSize, —最小检测窗口大小
Size maxObjectSize)—最大检测窗口大小(默认是图像大小)
三、函数使用
在进入detectMultiScal函数之前,首先需要对CascadeClassifier做初始化。
1. 初始化——read函数
CascadeClassifier的初始化很简单:
cv::CascadeClassifierclassifier;
classifier.load(“cascade.xml”);//这里的xml是训练得到的分类器xml
CascadeClassifier类中既有load也有read函数,二者是相同的,load将引用read函数。
1.1 xml的结构
训练得到的分类器以xml形式保存,整体上它包括stageType、featureType、height、width、stageParams、featureParams、stageNum、stages、features节点。
除stages和features外,其他主要是一些分类器的参数。
Stages中包含stageNum个stage(训练程序设定),每个stage中包含多个weakClassifiers,而每个weakClassifier中又包含一个internalNodes和一个leafValues。internalNodes中变量代表一个node,分别为node中的left/right标记、特征池中的ID和threshold。leafValues中两个变量代表一个node,分别为left leaf的值和right leaf的值。
而features是分类器的特征池,每个特征包含一个矩形。
1.2 read的过程
下面是read代码,主要包括从xml中获取两部分内容:data和featureEvaluator的读取。
详情参阅:http://blog.csdn.net/delltdk/article/details/9186875
1.3 read的结果
read的结果一是初始化了分类器的特征类型、最小检测窗口size等参数;二是建立级联的分类器树;三是提取了xml中的特征池。
2. detectMultiscale函数
在load分类器之后,可以调用该函数对一幅图像做多尺度检测。
1.1 颜色通道
如果输入是彩色图像,代码会自动转为灰度图。
1.2 缩放尺寸
输入图像尺寸必须大于分类器样本尺寸。
图像尺寸经缩放因子后,再四舍五舍得到尺寸。
ex1:
分类器:18*18;输入图像:24*24;detectMultiScale(frame_gray,vct_rc, 1.05, 1, 0, Size(20,20));
多尺度检测尺寸:22*22、21*21、20*20、19*19
ex2:
分类器:18*18;输入图像:24*24;detectMultiScale(frame_gray, vct_rc, 1.05, 1, 0, Size(21,21));
多尺度检测尺寸:21*21、20*20、19*19
ex3:
分类器:18*18;输入图像:24*24;detectMultiScale(frame_gray,vct_rc, 1.05, 1, 0, Size(22,22));
多尺度检测尺寸:20*20、19*19
ex4:
分类器:18*18;输入图像:26*26;detectMultiScale(frame_gray,vct_rc, 1.05, 1, 0, Size(22,22));
多尺度检测尺寸:21*21、20*20、19*19
1.3 并行计算
并行计算内容写在重载操作()函数体中。
classCV_EXPORTS ParallelLoopBody
{
public:
virtual~ParallelLoopBody();
virtual void operator() (const Range& range) const= 0;
};
CV_EXPORTSvoid parallel_for_(constRange& range, const ParallelLoopBody&body, double nstripes=-1.);
1) detectSingleScale函数中,setImage函数计算积分图,对于X个特征,根据对应的X个rect,分别计算各个rect的积分图,并进行存储。积分图是16维的int数组,跟矩形的对应关系如下图,每个rect产生8维特征:
2) setImage函数中,先将原图进行降采样,然后提取全图的积分图,然后根据updatePtrs函数分配给X个特征rect的积分图数组,放入featurePtr结构体数组中,有rect和intp[];
X个特征rect是训练分类器时分配的,每个rect的宽度和高度为一个block的宽高度;
3) CV_SUM_PTRS:目的是根据原图的积分图,计算特征rect的积分图数组。参数ptr为原图的积分图数据,tr为当前计算的rect,step为积分图的宽度;
#defineCV_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 , y + h) */ \
(p2) = sum + (rect).x + (step) * ((rect).y+ (rect).height), \
/* (x + w, y + h)*/ \
(p3) = sum + (rect).x + (rect).width +(step) * ((rect).y + (rect).height)
4) calc函数,根据rect的积分图16维int数据,获取8位二进制特征,所以样本特征维数是8*num(rect);
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。