训练自己的Adaboost级联分类器并识别物体(一)

来源:互联网 发布:linux mysql 开启日志 编辑:程序博客网 时间:2024/05/09 16:44

本教程旨在利用Adaboost算法结合OpenCV生成自己的级联分类器(一个.xml文件),并在本教程中利用该分类器识别所需的物体。教程分为以下四部:

  • 准备正负样本图片
  • 生成样本描述文件
  • 训练样本
  • 目标识别
————————————————————————————————————————————————————————————————————————

一、准备正负样本图片

1.1 正样本采集

正样本指的是所需要识别的物体的局部图像,应该尽可能只包含目标物体,不包含背景图片。正样本建议采用灰度图。
常用的有两种方式标定正样本。imageclipper和objectmarker,二者功能类似。本文采用objectmarker标定图像中的正样本区域。
ObjectMarker可以在此下载:ObjectMarker下载
在使用ObjectMarker标定正样本的过程中尽可能保证长宽一致,采集结果标识了正样本区域在图中的位置,放于代码目录下的info.txt下,如下图所示。
rawdata/1_1297_113.430269_34.526398.jpg 1 2 49 47 48rawdata/1_1298_113.430269_34.526398.jpg 1 1 35 43 44rawdata/1_1315_113.430269_34.526398.jpg 2 65 117 43 50 58 219 48 52rawdata/1_1316_113.430269_34.526398.jpg 2 59 109 46 51 49 218 46 50
其中rawdata文件夹存放了所有待标定的大图,objectMarker.exe与rawdata文件夹同级。

1.2 负样本采集

所谓负样本,是指不包含待识别物体的任何图片,因此你可以将天空、海滩、大山等所有东西都拿来当负样本。但是,很多时候你这样做是事倍功半的。大多数模式识别问题都是用在视频监控领域,摄像机的角度跟高度都相对固定。如果你知道你的项目中摄像机一般都在拍什么,那负样本可以非常有针对性地选取,而且可以事半功倍。举个例子,你现在想做火车站广场的异常行为检测,在这个课题中行人检测是必须要做的。而视频帧的背景基本都是广场的地板、建筑物等。那你可以在人空旷的时候选择取一张图,不同光照不同时段下各取一张图,然后在这些图上随机取图像块,每个块20x20,每个块就是一个负样本。这几张图就能缠上数以千计数以万计的负样本!而且针对性强。因为海洋、大山等东西对你的识别一点帮助也没有,还会增加训练的时间,吃力不讨好的事还是少做为好。我写了一段小程序,功能是根据背景图片自动随机生成指定数量指定尺寸的负样本:
#include <opencv/cv.h>#include <opencv/highgui.h>#include <iostream>#include <string>using namespace std;using namespace cv;//从背景图片中随机抽取图像块,多用于生成负样本#define kImageBlockWidth                50        //图像块大小#define kImageBlockHeight                50        #define kLoopTimes                        1000    //期望样本数int main(){int originX = 0, originY = 0;int width_limited = 0, height_limited = 0;int width = 0, height = 0;IplImage *bgImage = cvLoadImage("2.jpg");IplImage *blockImage = cvCreateImage(cvSize(kImageBlockWidth, kImageBlockHeight), bgImage->depth, bgImage->nChannels);width = bgImage->width;height = bgImage->height;width_limited = width - kImageBlockWidth;height_limited = height - kImageBlockHeight;cout << width_limited << "   " << height_limited;for (int i = 0; i < kLoopTimes; i++){originX = rand() % width_limited;originY = rand() % height_limited;cvZero(blockImage);CvPoint2D32f center_block = cvPoint2D32f(originX + kImageBlockWidth / 2, originY + kImageBlockHeight / 2);cvGetRectSubPix(bgImage, blockImage, center_block);char saveFileName[100] = { '\0' };sprintf(saveFileName, "neg\\(%d).jpg", i + 1);cvSaveImage(saveFileName, blockImage);}cvReleaseImage(&bgImage);cvReleaseImage(&blockImage);system("pause");return 0;}

这里的负样本尺寸我设定为50x50,是因为在我的应用环境下待识别的物体差不多是这个尺寸的。具体可以分析一下你的info.txt文件。生成文件后,按以下步骤操作:

  1. 开cmd.exe cd到该目录
  2. 然后运行“dir /b > sample_neg.dat”,该命令会将目录下所有文件名输出到sample_neg.dat文件中

  对于负样本,我还有一点要说明:负样本图像的大小只要不小于正样本就可以。opencv在使用你提供的一张负样本图片时会自动从其中抠出一块与正样本同样大小的图像作为负样本,具体的函数可见opencv系统函数cvGetNextFromBackgroundData()。


二、生成样本描述文件

对于负样本,只需要以上1.2得到的.dat文件即可。对于正样本图片,需要获得.vec文件。在生成描述文件过程中,我们需要用到opencv自带的opencv_createsamples.exe可执行文件。这个文件一般存放在opencv安装目录的/bin文件夹下(请善用ctrl+F搜索)。如果没有,可以自己编译一遍也很快。
另外创建一个文件夹,包含pos、neg两个子文件夹。此处是指没标定的大图。

2.1 修改样本描述文件的格式

在1.1中我们得到了info.txt,在此我们利用UltraEdit、Notepad等某种文本编辑工具将" rawdata/ "替换掉,并将文件命名为sample_pos.dat。

2.2 使用opencv_createsamples.exe创建样本描述文件:

使用CMD运行以下命令:
opencv_createsamples.exe -info ./pos/sample_pos.dat -vec ./pos/sample_pos.vec -num 101 -w 20 -h 20 -show NO
参数说明:
-info,指样本说明文件-vec,样本描述文件的名字及路径-num,总共几个样本,要注意,这里的样本数是指标定后的20x20的样本数,而不是大图的数目,其实就是样本说明文件第2列的所有数字累加和。-w -h 指明想让样本缩放到什么尺寸。这里的奥妙在于你不必另外去处理第1步中被矩形框出的图片的尺寸,因为这个参数帮你统一缩放!-show 是否显示每个样本。样本少可以设为YES,要是样本多的话最好设为NO,或者不要显式地设置,因为关窗口会关到你哭
done表示创建成功,若创建不成功会报错,大部分会提示你sample.dat pars error,一般是说明文件格式有错,或者num设置过大
Create training samples from images collection...Done. Created 101 samples

三、总结

1.样本图片最好使用灰度图,且最好能根据实际情况做一定的预处理

2.样本选择的原则是:数量越多越好,尽量高于1000;样本间差异性越大越好

3.正负样本比例为1:3最佳,尺寸为20x20最佳



0 0
原创粉丝点击