当前位置:   article > 正文

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

detectmultiscale

注:部分内容转载自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);

 

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号