您的位置:首页 > 运维架构

Opencv2.4.9多尺度检测detectMultiScale函数源码分析

2016-09-06 16:26 302 查看
注:部分内容转载自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);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息