【原】训练自己haar-like特征分类器并识别物体(1)
本系列文章旨在学习如何在opencv中基于haar-like特征训练自己的分类器,并且用该分类器用于模式识别。该过程大致可以分为一下几个大步骤:
1.准备训练样本图片,包括正例及反例样本
2.生成样本描述文件
3.训练样本
4.目标识别
=================
本文主要对步骤1、步骤2进行说明。
1.准备训练样本图片,包括正例及反例样本
1)正样本的采集:
所谓正样本,是指只包含待识别的物体的图片,一般是一些局部的图片,且最好能转化为灰度图。比如,若你想识别人脸,则正样本应尽可能只包含人脸,可以留一点周边的背景但不要过多。在正样本的采集上,我们有两种图形标定工具可以使用:(1)opencv的imageClipper (2)objectMarker。这两个工具都支持傻瓜式地对图片中的物体进行矩形标定,可以自动生成样本说明文件,自动逐帧读取文件夹内的下一帧。我用的是objectMarker。如果你找不到这个软件,可以留下邮箱,我发给你。
在标定的时候尽量保持长宽比例一致,也就是尽量用接近正方形的矩形去标定待识别的物体,至于正方形的大小影响并不大。尽管OpenCV推荐训练样本的最佳尺寸是20x20,但是在下一步生成样本描述文件时可以轻松地将其它尺寸缩放到20x20。标定完成后生成的样本说明文件info.txt内容举例如下:
rawdata/ (1).bmp 1 118 26 81 72
rawdata/ (10).bmp 2 125 72 48 46 0 70 35 43
rawdata/ (11).bmp 1 105 87 43 42
rawdata/ (12).bmp 2 1 70 34 38 105 87 41 44
...
其中rawdata文件夹存放了所有待标定的大图,objectMarker.exe与rawdata文件夹同级。这个描述文件的格式已经很接近opencv所要求的了。
2)负样本的采集:
所谓负样本,是指不包含待识别物体的任何图片,因此你可以将天空、海滩、大山等所有东西都拿来当负样本。但是,很多时候你这样做是事倍功半的。大多数模式识别问题都是用在视频监控领域,摄像机的角度跟高度都相对固定。如果你知道你的项目中摄像机一般都在拍什么,那负样本可以非常有针对性地选取,而且可以事半功倍。举个例子,你现在想做火车站广场的异常行为检测,在这个课题中行人检测是必须要做的。而视频帧的背景基本都是广场的地板、建筑物等。那你可以在人空旷的时候选择取一张图,不同光照不同时段下各取一张图,然后在这些图上随机取图像块,每个块20x20,每个块就是一个负样本。这几张图就能缠上数以千计数以万计的负样本!而且针对性强。因为海洋、大山等东西对你的识别一点帮助也没有,还会增加训练的时间,吃力不讨好的事还是少做为好。我写了一段小程序,功能是根据背景图片自动随机生成指定数量指定尺寸的负样本:
#include "stdafx.h"
#include "cv.h"
#include "highgui.h"
#include <iostream>
#include <string> using namespace std;
using namespace cv; //从背景图片中随机抽取图像块,多用于生成负样本
#define kImageBlockWidth 40 //图像块大小
#define kImageBlockHeight 40
#define kLoopTimes 1000 //期望样本数 int _tmain(int argc, _TCHAR* argv[])
{
int originX = , originY = ;
int width_limited = , height_limited = ;
int width = , height = ;
IplImage *bgImage = cvLoadImage("neg\\bg1.bmp");
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 = ; i < kLoopTimes; i++)
{
originX = rand() % width_limited;
originY = rand() % height_limited;
cvZero(blockImage);
CvPoint2D32f center_block = cvPoint2D32f(originX + kImageBlockWidth / , originY + kImageBlockHeight / );
cvGetRectSubPix(bgImage, blockImage, center_block);
char saveFileName[] = {'\0'};
sprintf(saveFileName, "neg\\(%d).bmp", i + );
cvSaveImage(saveFileName, blockImage);
} cvReleaseImage(&bgImage);
cvReleaseImage(&blockImage);
system("pause");
return ;
}
负样本生成代码
这里的负样本尺寸我设定为40x40,是因为在我的应用环境下待识别的物体差不多是这个尺寸的。具体可以分析一下你的info.txt文件。生成文件后,开cmd.exe cd到该目录,然后运行“dir /b > neg_sample.dat”,打开.dat,用editplus替换bmp为bmp 1 0 0 40 40。这样负样本说明文件就产生了。
对于负样本,我还有一点要说明:负样本图像的大小只要不小于正样本就可以。opencv在使用你提供的一张负样本图片时会自动从其中抠出一块与正样本同样大小的图像作为负样本,具体的函数可见opencv系统函数cvGetNextFromBackgroundData()。
2.生成样本描述文件
样本描述文件也即.vec文件,里面存放二进制数据,是为opencv训练做准备的。只有正样本需要生成.vec文件,负样本不用,负样本用.dat文件就够。在生成描述文件过程中,我们需要用到opencv自带的opencv_createsamples.exe可执行文件。这个文件一般存放在opencv安装目录的/bin文件夹下(请善用ctrl+F搜索)。如果没有,可以自己编译一遍也很快。这里提供懒人版:http://en.pudn.com/downloads204/sourcecode/graph/texture_mapping/detail958471_en.html 这是别人编译出来的opencv工程,在bin底下可以找到该exe文件。要注意,该exe依赖于cv200.dll、cxcore200.dll、highgui200.dll这三个动态库,要保持这四个文件在同个目录下。

现在我们开始生成描述文件。新建文件夹pos、neg分别存放正样本及负样本图片,此处是指没标定的大图。
1)修改样本说明文件的格式:
在第1步中我们用objectMarker完成标定后会自动生成info.txt,现在我们需要对其格式做一定的微调,通过editplus或者ultraedit将路径信息rawdata都替换掉,并命名为sample_pos.dat,也可自定义名字。
(1).bmp 1 118 26 81 72
(10).bmp 2 125 72 48 46 0 70 35 43
(11).bmp 1 105 87 43 42
(12).bmp 2 1 70 34 38 105 87 41 44
(13).bmp 1 102 93 43 41
(14).bmp 1 104 86 45 47
2)使用opencv_createsamples.exe创建样本描述文件:
打开cmd.exe,cd到opencv_createsamples.exe所在的目录,执行命令:
opencv_createsamples.exe -info ./pos/sample_pos.dat -vec ./pos/sample_pos.vec -num 17 -w 20 -h 20 -show YES
参数说明:-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 17 samples
总结
总结并延伸以上内容:
1.样本图片最好使用灰度图,且最好能根据实际情况做一定的预处理
2.样本选择的原则是:数量越多越好,尽量高于1000;样本间差异性越大越好
3.正负样本比例为1:3最佳,尺寸为20x20最佳
That`s all。
==================
附上参考资料,看这些就够,网上资料太多容易让人看花眼!
http://blog.csdn.net/think_embed/article/details/9959569
http://www.docin.com/p-80649093.html
http://jingyan.baidu.com/article/4dc40848f50689c8d946f197.html
http://blog.csdn.net/carson2005/article/details/8171571
objectMarker下载链接【20151218更新】
http://download.csdn.net/download/lglgaigogo/1197957
【原】训练自己haar-like特征分类器并识别物体(1)的更多相关文章
- 【原】训练自己的haar-like特征分类器并识别物体(3)
在前两篇文章中,我介绍了<训练自己的haar-like特征分类器并识别物体>的前三个步骤: 1.准备训练样本图片,包括正例及反例样本 2.生成样本描述文件 3.训练样本 4.目标识别 == ...
- 【原】训练自己haar-like特征分类器并识别物体(2)
在上一篇文章中,我介绍了<训练自己的haar-like特征分类器并识别物体>的前两个步骤: 1.准备训练样本图片,包括正例及反例样本 2.生成样本描述文件 3.训练样本 4.目标识别 == ...
- 使用OpenCV训练Haar like+Adaboost分类器的常见问题
<FAQ:OpenCV Haartraining>——使用OpenCV训练Haar like+Adaboost分类器的常见问题 最近使用OpenCV训练Haar like+Adaboost ...
- 【macOS】 在OpenCV下训练Haar特征分类器
本教程基于以下环境 macOS 10.12.6,OpenCV 3.3.0,python 3.6.由于网上基于masOS系统的教程太少,想出一篇相关教程造福大家-本文旨在学习如何在opencv中基于ha ...
- opencv - haar人脸特征的训练
step 1: 把正样品,负样品,opencv_createsamples,opencv_haartraining放到一个文件夹下面,利于后面的运行.step 2: 生成正负样品的描述文件 正样品描述 ...
- 【原/转】opencv的级联分类器训练与分类全程记录
众所周知,opencv下有自带的供人脸识别以及行人检测的分类器,也就是说已经有现成的xml文件供你用.如果我们不做人脸识别或者行人检测,而是想做点其他的目标检测该怎么做呢?答案自然是自己训练一个特定的 ...
- AdaBoost中利用Haar特征进行人脸识别算法分析与总结1——Haar特征与积分图
原地址:http://blog.csdn.net/watkinsong/article/details/7631241 目前因为做人脸识别的一个小项目,用到了AdaBoost的人脸识别算法,因为在网上 ...
- CNN基础二:使用预训练网络提取图像特征
上一节中,我们采用了一个自定义的网络结构,从头开始训练猫狗大战分类器,最终在使用图像增强的方式下得到了82%的验证准确率.但是,想要将深度学习应用于小型图像数据集,通常不会贸然采用复杂网络并且从头开始 ...
- Spark Mllib里如何将trainDara训练数据的分类特征字段转换为数值字段(图文详解)
不多说,直接上干货! 字段3 是分类特征字段,但是呢,在分类算法里不能直接用.所以,必须要转换为数值字段才能够被分类算法使用. 具体,见 Hadoop+Spark大数据巨量分析与机器学习整合开发实战的 ...
随机推荐
- 如何将ToolBar 样式设置Title文字水平居中
以下是我的activity.xml的代码,线性布局.<android.support.v7.widget.Toolbar android:id="@+id/toolba ...
- [转载]SharePoint 2013测试环境安装配置指南
软件版本 Windows Server 2012 标准版 SQL Server 2012 标准版 SharePoint Server 2013 企业版 Office Web Apps 2013 备注: ...
- php中mysql操作的buffer知识
php与mysql的连接有三种方式,mysql,mysqli,pdo.不管使用哪种方式进行连接,都有使用buffer和不使用buffer的区别. 什么叫使用buffer和不使用buffer呢? 客户端 ...
- Angular系列---- AngularJS入门教程03:AngularJS 模板(转载)
是时候给这些网页来点动态特性了——用AngularJS!我们这里为后面要加入的控制器添加了一个测试. 一个应用的代码架构有很多种.对于AngularJS应用,我们鼓励使用模型-视图-控制器(MVC)模 ...
- C#获取本地或远程磁盘使用信息
因为公司有多个服务器,要检查磁盘的使用情况确定程序放哪个服务器和清理垃圾,所以写个小程序帮忙检查. 效果图: 后台代码: private void btnCheck_Click(object send ...
- 使用VS开发C语言
在嵌入开发板上做了一段时间的C语言开发后,今天突然心血来潮,想起大学时期在TurboC和TC3下写代码的情形.大一时宿舍里有台386(在当时是算比较先进的了),大一大二基本上都在玩DOS和WIN31. ...
- php配合jquery实现增删操作
后台使用php,前台引用jquery,实现增删操作,代码如下: <script type="text/javascript" src="http://keleyi. ...
- [CLR via C#]25. 线程基础
一.Windows为什么要支持线程 Microsoft设计OS内核时,他们决定在一个进程(process)中运行应用程序的每个实例.进程不过是应用程序的一个实例要使用的资源的一个集合.每个进程都赋予了 ...
- 【C#】1.2 控制台应用程序学习要点
分类:C#.VS2015 创建日期:2016-06-14 教材:十二五国家级规划教材<C#程序设计及应用教程>(第3版) 一.要点概述 <C#程序设计及应用教程>(第3版)的第 ...
- 第一个app.总结
前记: 最近想整点外快,但是又没啥子技术,唉,学了一下android,想写点游戏啥的,,唉,可惜,美工,UI始终不行,代码也勉勉强强... 不过总的来说也是收获参半吧,也是有一些新的知识学到了嘛,至少 ...