opencv分类器基础

有点时间研究强大的OpenCV,对于图像识别方面概念入门的内容在网上找到这篇文章,很有帮助,做个收藏,也方便以后有相同需要的同学们方便使用。

原文地址:http://wenjuanhe.blog.163.com/blog/static/745017252009102101728454

 
 /

目标检测方法最初由Paul Viola [Viola01]提出,并由Rainer Lienhart [Lienhart02]对这一方法

进行了改善. 首先,利用样本(大约几百幅样本图片)的 harr 特征进行分类器训练,得到一个级

联的boosted分类器。训练样本分为正例样本和反例样本,其中正例样本是指待检目标样本(例如人

脸或汽车等),反例样本指其它任意图片,所有的样本图片都被归一化为同样的尺寸大小(例如,

20x20)。

分类器训练完以后,就可以应用于输入图像中的感兴趣区域(与训练样本相同的尺寸)的检测。检测

到目标区域(汽车或人脸)分类器输出为1,否则输出为0。为了检测整副图像,可以在图像中移动搜

索窗口,检测每一个位置来确定可能的目标。 为了搜索不同大小的目标物体,分类器被设计为可以

进行尺寸改变,这样比改变待检图像的尺寸大小更为有效。所以,为了在图像中检测未知大小的目

标物体,扫描程序通常需要用不同比例大小的搜索窗口对图片进行几次扫描。

分类器中的“级联”是指最终的分类器是由几个简单分类器级联组成。在图像检测中,被检窗口依

次通过每一级分类器, 这样在前面几层的检测中大部分的候选区域就被排除了,全部通过每一级分

类器检测的区域即为目标区域。 目前支持这种分类器的boosting技术有四种: Discrete

Adaboost, Real Adaboost, Gentle Adaboost and Logitboost。"boosted" 即指级联分类器的每一

层都可以从中选取一个boosting算法(权重投票),并利用基础分类器的自我训练得到。基础分类器

是至少有两个叶结点的决策树分类器。 Haar特征是基础分类器的输入,主要描述如下。目前的算法

主要利用下面的Harr特征。
 

 

每个特定分类器所使用的特征用形状、感兴趣区域中的位置以及比例系数(这里的比例系数跟检测

时候采用的比例系数是不一样的,尽管最后会取两个系数的乘积值)来定义。例如在第三行特征

(2c)的情况下,响应计算为复盖全部特征整个矩形框(包括两个白色矩形框和一个黑色矩形框)象素

的和减去黑色矩形框内象素和的三倍 。每个矩形框内的象素和都可以通过积分图象很快的计算出来

。(察看下面和对cvIntegral的描述).

通过HaarFaceDetect 的演示版可以察看目标检测的工作情况。

下面只是检测部分的参考手册。 haartraining是它的一个单独的应用,可以用来对系列样本训练级

联的 boosted分类器。详细察看opencv/apps/haartraining。

 

 

CvHaarFeature, CvHaarClassifier, CvHaarStageClassifier, CvHaarClassifierCascade
Boosted Haar 分类器结构

#define CV_HAAR_FEATURE_MAX 

 
 3


typedef struct CvHaarFeature
{
 

 
   
 
   
 
 int  
 
 tilted;  
 

  
 
   
 
   
 
   
 

  
 
   
 
   
 

  
 
   
 
   
 
 struct
  
 
   
 
   
 
 {
  
 
   
 
   
 
   
 
   
 
   
 
   
 
 CvRect r;
  
 
   
 
   
 
   
 
   
 
   
 
   
 
 float weight;
  
 
   
 
   
 
 } rect[CV_HAAR_FEATURE_MAX];
}
CvHaarFeature;


typedef struct CvHaarClassifier
{
 

 
   
 
   
 
 int count;  
 

 

 
   
 
   
 

  
 
   
 
   
 
 CvHaarFeature* haar_feature;
  
 
   
 
   
 
 float* threshold;
  
 
   
 
   
 
 int* left;
  
 
   
 
   
 
 int* right;
  
 
   
 
   
 
 float* alpha;
}
CvHaarClassifier;


typedef struct CvHaarStageClassifier
{
 

 
   
 
   
 
 int  
 
 count;  
 

  
 
   
 
   
 
 float threshold;
  
 
   
 
   
 
 CvHaarClassifier* classifier;

 

 
   
 
   
 

  
 
   
 
   
 
 int next;
  
 
   
 
   
 
 int child;
  
 
   
 
   
 
 int parent;
}
CvHaarStageClassifier;

typedef struct CvHidHaarClassifierCasca

 
 de CvHidHaarClassifierCasca 
 
 de;


typedef struct CvHaarClassifierCascade
{
 

 
   
 
   
 
 int  
 
 flags;
  
 
   
 
   
 
 int  
 
 count;
  
 
   
 
   
 
 CvSize orig_window_size;

 

 
   
 
   
 

  
 
   
 
   
 
 CvSize real_window_size;
  
 
   
 
   
 
 double scale;
  
 
   
 
   
 
 CvHaarStageClassifier* stage_classifier;
  
 
   
 
   
 
 CvHidHaarClassifierCasca 
 
 de* hid_cascade;
}
CvHaarClassifierCascade;
所有的结构都代表一个级联boosted Haar分类器。级联有下面的等级结构:

Cascade: 

 

Stage1:  
 

Classifier11:  
 

Feature11  
 

Classifier12:  
 

Feature12  
 

...  
 

Stage2:  
 

Classifier21:  
 

Feature21  
 

...  
 

...  
 

整个等级可以手工构建,也可以利用函数cvLoadHaarClassifierCasc 
 
 ade从已有的磁盘文件或嵌入式

基中导入。

cvLoadHaarClassifierCasc

 
 ade
从文件中装载训练好的级联分类器或者从OpenCV中嵌入的分类器数据库中导入

CvHaarClassifierCascade* cvLoadHaarClassifierCasc

 
 ade(
  
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
 const char* directory,
  
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
 CvSize orig_window_size );
directory  
 

训练好的级联分类器的路径  
 

orig_window_size  
 

级联分类器训练中采用的检测目标的尺寸。因为这个信息没有在级联分类器中存储,所有要单独指

出。 

 

函数 cvLoadHaarClassifierCasc 
 
 ade 用于从文件中装载训练好的利用海尔特征的级联分类器,或者

从OpenCV中嵌入的分类器数据库中导入。分类器的训练可以应用函数haartraining(详细察看

opencv/apps/haartraining) 这个数值是在训练分类器时就确定好的,修改它并不能改变检测的范

围或精度。

需要注意的是,这个函数已经过时了。现在的目标检测分类器通常存储在 XML 或 YAML 文件中,而

不是通过路径导入。从文件中导入分类器,可以使用函数 cvLoad 。

cvReleaseHaarClassifierC

 
 ascade
释放haar classifier cascade。

void cvReleaseHaarClassifierC

 
 ascade( CvHaarClassifierCascade** cascade );
cascade  
 

双指针类型指针指向要释放的cascade. 指针由函数声明。  
 

函数 cvReleaseHaarClassifierC 
 
 ascade 释放cascade的动态内存,其中cascade的动态内存或者是

手工创建,或者通过函数 cvLoadHaarClassifierCasc

 
 ade 或 cvLoad分配。

cvHaarDetectObjects
检测图像中的目标

typedef struct CvAvgComp
{
 

 
   
 
   
 
 CvRect rect;
  
 
   
 
   
 
 int neighbors;
}
CvAvgComp;

CvSeq* cvHaarDetectObjects( const CvArr* image, CvHaarClassifierCascade* cascade,
 

 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
 CvMemStorage* storage, double scale_factor=1.1,
  
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
 int min_neighbors=3, int flags=0,
  
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
 CvSize min_size=cvSize(0,0) );
image  
 

被检图像  
 

cascade  
 

harr 分类器级联的内部标识形式  
 

storage  
 

用来存储检测到的一序列候选目标矩形框的内存区域。  
 

scale_factor  
 

在前后两次相继的扫描中,搜索窗口的比例系数。例如1.1指将搜索窗口依次扩大10%。  
 

min_neighbors  
 

构成检测目标的相邻矩形的最小个数(缺省-1)。如果组成检测目标的小矩形的个数和小于

min_neighbors-1 都会被排除。如果min_neighbors 为 0, 则函数不做任何操作就返回所有的被检

候选矩形框,这种设定值一般用在用户自定义对检测结果的组合程序上。 

 

flags  
 

操作方式。当前唯一可以定义的操作方式是 CV_HAAR_DO_CANNY_PRUNING。如果被设定,函数利用

Canny边缘检测器来排除一些边缘很少或者很多的图像区域,因为这样的区域一般不含被检目标。人

脸检测中通过设定阈值使用了这种方法,并因此提高了检测速度。 

 

min_size  
 

检测窗口的最小尺寸。缺省的情况下被设为分类器训练时采用的样本尺寸(人脸检测中缺省大小是

~20×20)。 

 

  
 
   
 
 函数 cvHaarDetectObjects 使用针对某目标物体训练的级联分类器在图像中找到包含目标物体

的矩形区域,并且将这些区域作为一序列的矩形框返回。函数以不同比例大小的扫描窗口对图像进

行几次搜索(察看cvSetImagesForHaarClassi

 
 fierCascade)。 每次都要对图像中的这些重叠区域利

用cvRunHaarClassifierCasca

 
 de进行检测。 有时候也会利用某些继承(heuristics)技术以减少分

析的候选区域,例如利用 Canny 裁减 (prunning)方法。 函数在处理和收集到候选的方框(全部

通过级联分类器各层的区域)之后,接着对这些区域进行组合并且返回一系列各个足够大的组合中的

平均矩形。调节程序中的缺省参数(scale_factor=1.1, min_neighbors=3, flags=0)用于对目标进

行更精确同时也是耗时较长的进一步检测。为了能对视频图像进行更快的实时检测,参数设置通常

是:scale_factor=1.2, min_neighbors=2, flags=CV_HAAR_DO_CANNY_PRUNING,

min_size=<minimum possible face size> (例如, 对于视频会议的图像区域).
例子:利用级联的Haar classifiers寻找检测目标(e.g. faces).

#include "cv.h"
#include "highgui.h"

CvHaarClassifierCascade* load_object_detector( const char* cascade_path )
{
 

 
   
 
   
 
 return (CvHaarClassifierCascade*)cvLoad( cascade_path );
}

void detect_and_draw_objects( IplImage* image,
 

 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
 CvHaarClassifierCascade* cascade,
  
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
 int do_pyramids )
{
  
 
   
 
   
 
 IplImage* small_image = image;
  
 
   
 
   
 
 CvMemStorage* storage = cvCreateMemStorage(0);
  
 
   
 
   
 
 CvSeq* faces;
  
 
   
 
   
 
 int i, scale = 1;

 

 
   
 
   
 

  
 
   
 
   
 
 if( do_pyramids )
  
 
   
 
   
 
 {
  
 
   
 
   
 
   
 
   
 
   
 
   
 
 small_image = cvCreateImage( cvSize(image->width/2,image->height/2),

IPL_DEPTH_8U, 3 );
 

 
   
 
   
 
   
 
   
 
   
 
   
 
 cvPyrDown( image, small_image, CV_GAUSSIAN_5x5 );
  
 
   
 
   
 
   
 
   
 
   
 
   
 
 scale = 2;
  
 
   
 
   
 
 }

 

 
   
 
   
 

  
 
   
 
   
 
 faces = cvHaarDetectObjects( small_image, cascade, storage, 1.2, 2,

CV_HAAR_DO_CANNY_PRUNING );

 

 
   
 
   
 

  
 
   
 
   
 
 for( i = 0; i < faces->total; i++ )
  
 
   
 
   
 
 {
  
 
   
 
   
 
   
 
   
 
   
 
   
 

  
 
   
 
   
 
   
 
   
 
   
 
   
 
 CvRect face_rect = *(CvRect*)cvGetSeqElem( faces, i, 0 );
  
 
   
 
   
 
   
 
   
 
   
 
   
 
 cvRectangle( image, cvPoint(face_rect.x*scale,face_rect.y*scale),
  
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
 cvPoint((face_rect.x+face_rect.width)*scale,
  
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
 (face_rect.y+face_rect.height)*scale),
  
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
 CV_RGB(255,0,0), 3 );
  
 
   
 
   
 
 }

 

 
   
 
   
 
 if( small_image != image )
  
 
   
 
   
 
   
 
   
 
   
 
   
 
 cvReleaseImage( &small_image );
  
 
   
 
   
 
 cvReleaseMemStorage( &storage );
}


int main( int argc, char** argv )
{
 

 
   
 
   
 
 IplImage* image;
  
 
   
 
   
 
 if( argc==3 && (image = cvLoadImage( argv[1], 1 )) != 0 )
  
 
   
 
   
 
 {
  
 
   
 
   
 
   
 
   
 
   
 
   
 
 CvHaarClassifierCascade* cascade = load_object_detector(argv[2]);
  
 
   
 
   
 
   
 
   
 
   
 
   
 
 detect_and_draw_objects( image, cascade, 1 );
  
 
   
 
   
 
   
 
   
 
   
 
   
 
 cvNamedWindow( "test", 0 );
  
 
   
 
   
 
   
 
   
 
   
 
   
 
 cvShowImage( "test", image );
  
 
   
 
   
 
   
 
   
 
   
 
   
 
 cvWaitKey(0);
  
 
   
 
   
 
   
 
   
 
   
 
   
 
 cvReleaseHaarClassifierC 
 
 ascade( &cascade );
  
 
   
 
   
 
   
 
   
 
   
 
   
 
 cvReleaseImage( &image );
  
 
   
 
   
 
 }

 

 
   
 
   
 
 return 0;
}
cvSetImagesForHaarClassi 
 
 fierCascade
为隐藏的cascade(hidden cascade)指定图像

void cvSetImagesForHaarClassi

 
 fierCascade( CvHaarClassifierCascade* cascade,
  
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
 const CvArr* sum, const CvArr* sqsum,
  
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
 const CvArr* tilted_sum, double scale );
cascade  
 

隐藏 Harr 分类器级联 (Hidden Haar classifier cascade), 由函数

cvCreateHidHaarClassifie

 
 rCascade生成  
 

sum  
 

32-比特,单通道图像的积分图像(Integral (sum) 单通道 image of 32-比特 integer format)

. 这幅图像以及随后的两幅用于对快速特征的评价和亮度/对比度的归一化。 它们都可以利用函数

cvIntegral从8-比特或浮点数 单通道的输入图像中得到。 

 

sqsum  
 

单通道64比特图像的平方和图像  
 

tilted_sum  
 

单通道32比特整数格式的图像的倾斜和(Tilted sum)  
 

scale  
 

cascade的窗口比例. 如果 scale=1, 就只用原始窗口尺寸检测 (只检测同样尺寸大小的目标物体)

- 原始窗口尺寸在函数cvLoadHaarClassifierCasc

 
 ade中定义 (在 "<default_face_cascade>"中缺

省为24x24), 如果scale=2, 使用的窗口是上面的两倍 (在face cascade中缺省值是48x48 )。 这样

尽管可以将检测速度提高四倍,但同时尺寸小于48x48的人脸将不能被检测到。 

 

函数 cvSetImagesForHaarClassi 
 
 fierCascade 为hidden classifier cascade 指定图像 and/or 窗

口比例系数。 如果图像指针为空,会继续使用原来的图像(i.e. NULLs 意味这"不改变图像")。比

例系数没有 "protection" 值,但是原来的值可以通过函数 cvGetHaarClassifierCasca

 
 deScale 重

新得到并使用。这个函数用于对特定图像中检测特定目标尺寸的cascade分类器的设定。函数通过

cvHaarDetectObjects进行内部调用,但当需要在更低一层的函数cvRunHaarClassifierCasca

 
 de中使

用的时候,用户也可以自行调用。

cvRunHaarClassifierCasca

 
 de
在给定位置的图像中运行 cascade of boosted classifier

int cvRunHaarClassifierCasca

 
 de( CvHaarClassifierCascade* cascade,
  
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
   
 
 CvPoint pt, int start_stage=0 );
cascade  
 

Haar 级联分类器  
 

pt  
 

待检测区域的左上角坐标。待检测区域大小为原始窗口尺寸乘以当前设定的比例系数。当前窗口尺

寸可以通过cvGetHaarClassifierCasca

 
 deWindowSize重新得到。  
 

start_stage  
 

级联层的初始下标值(从0开始计数)。函数假定前面所有每层的分类器都已通过。这个特征通过函

数cvHaarDetectObjects内部调用,用于更好的处理器高速缓冲存储器。 

 

函数 cvRunHaarHaarClassifierC 
 
 ascade 用于对单幅图片的检测。在函数调用前首先利用

cvSetImagesForHaarClassi

 
 fierCascade设定积分图和合适的比例系数 (=> 窗口尺寸)。当分析的矩

形框全部通过级联分类器每一层的时返回正值(这是一个候选目标),否则返回0或负值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值