码迷,mamicode.com
首页 > 其他好文 > 详细

目标检测程序开发(三)——级联分类器训练

时间:2015-07-24 10:45:38      阅读:191      评论:0      收藏:0      [点我收藏+]

标签:分类器训练   boosting   opencv   

目标检测分为3个阶段

1.      样本创建

2.      训练分类器

3.      使用训练好的分类器进行目标检测

 

级联分类器

源地址http://www.opencv.org.cn/opencvdoc/2.3.2/html/modules/objdetect/doc/cascade_classification.html

基于Haar特征的用于目标检测的级联分类器

下面描述的目标检测器最初由PaulViola提出,由RainerLienhart改进,

论文分别是Paul Viola and Michael J.Jones. Rapid Object Detection using a Boosted Cascade of Simple Features. IEEECVPR, 2001. The paper is available online athttp://www.ai.mit.edu/people/viola/

RainerLienhart and Jochen Maydt. An Extended Set of Haar-like Features for RapidObject Detection. IEEE ICIP 2002, Vol. 1, pp. 900-903, Sep. 2002. This paper,as well as the extended technical report, can be retrieved athttp://www.lienhart.de/Publications/publications

首先,一个分类器(这里指的是使用类Haar特征的提升的分类器的级联)由几百个特定的目标(一张脸或一辆汽车)样本训练,这些目标称为正样本,缩放到了相同的大小(比如20x20),训练还需要负样本,相同大小的任意图片

一个分类器训练之后,它可以应用到输入图像的感兴趣的区域(和训练时使用的大小相同)。如果这个区域很可能显示了目标(脸或汽车),分类器输出1,否则输出0.为了在整个图像中搜索目标,可以在整个图片中移动搜索窗口并使用分类器检查每个窗口。考虑到我们感兴趣的目标可能大小不同,分类器被设计为可以很容易的调整大小,这比调整图片的大小要更高效。所以寻找一个未知大小的目标,扫描程序可能需要按照不同大小扫描多次。

分类器名字中的”级联“Cascade指的是最后的分类器包含几个简单的分类器(stage),这些stage依次应用到一个感兴趣的区域,直到某个stage下拒绝这个区域(stage检测为不是目标)或者全部的stage都通过了这个区域,就是说全都检测为目标。”提升“boosted的意思是级联分类器的每一个stage自身是复杂的,是使用某一种提升技巧组合基本的分类器构建而成,当前支持DiscreteAdaboost, Real Adaboost, Gentle Adaboost and Logitboost 4种。基本分类器是至少有两个叶子的决策树。类Haar特征是基本分类器的输入。当前算法使用下列类Haar特征

技术分享

一个特定的分类器使用的特征由它检测区域的形状,位置以及大小指定,由浅色区域累加值减去深色区域累加值计算,矩形区域的像素值之和可以用积分图快速计算。

新的C++接口也支持LBP特征。

 

样本创建和分类器训练

我刚刚发现级联分类器的训练有中文版的官方文档,,,

http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/user_guide/ug_traincascade.html

里面对于样本创建和级联分类器的训练描述很具体,里面的辅助工具在配置环境变量的时候已经用过一个,用来验证环境变量配置是否成功,使用的时候直接在命令行里使用即可。

 

下面是我的操作的记录

我检测的目标是戴眼镜的头部

技术分享

我的目录结构如图所示,neg文件夹里存放负样本,pos文件夹里存放正样本,正样本是我手动从图片里截出来的,只包含正样本,但是大小不同,所以需要后面使用工具创建样本

 技术分享

①生成bg.txt文件:在0723目录下【新建】cmd.txt文件,写进cmd.exe,然后保存,把后缀名改为bat,双击运行cmd.bat,输入 dir /bneg > bg.txt,得到bg.txt文件

技术分享

然后使用记事本的【替换】功能,把My全部替换为neg/My,将文件的每一行改为neg/MyPhoto2015_0721_190001.jpg的形式

 技术分享

②生成info.dat文件:根据官网文档,结合我的目录结构,info.dat的每一行应该是

pos/MyPhoto2015_0721_193020.jpg  1 0  0 167 251的形式,我的正样本已经手动裁剪过了,并且每个样本只含有一个数目,所以后面跟着 1 位置是 0 0,但是我的样本大小是不一样的,我的正样本大概有五百个,一个个手动添加太麻烦,我写了几行java程序GetInfo.java(附在本文最后),读取图片的宽高像素,直接写到info.dat文件,里面硬编码了路径,只有一个命令行参数,区分当前是哪个目录,区分是training下的0722目录还是0723目录,使用如下:

新建一个getinfo.bat文件,内容如下:0723就是指定目录

javac GetInfo.java

java GetInfo 0723

pause

双击运行后结果如下:

技术分享

已经符合要求

 

③下一步就是创建样本

新建一个create_samples.bat文件,内容如下:

del p.vec

pause

opencv_createsamples  -info info.dat  -vec p.vec -w 50  -h 50  -show TRUE -num 580

pause

各个参数就是根据官方文档给出的含义设定的

双击运行后如下,可以看到已经生成的p.vec文件

技术分享

④开始训练,还是创建一个start_traing.bat文件,用批处理文件的好处不用每次训练的时候都要手动敲一长串命令,可以简单修改后重复使用。内容如下:

opencv_traincascade   -data ./RESULT   -vec p.vec -bg bg.txt   -numPos 500   -numNeg 300   -numStages  5  ^

-stageType BOOST   -featureType HAAR -w50   -h 50  ^

-bt GAB  -minHitRate 0.995  -maxFalseAlarmRate  0.5  -weightTrimRate  0.95  -maxDepth 1   -maxWeakCount 1  ^

-mode ALL  > train.log

我把它的输出重定向到了train.log 文件里面

注意^后面不能有多余空格

最好手动创建RESULT文件夹,否则好像会出错,还有训练的参数很多,要理解每个参数的意义,填写正确,比如我当时急于开始训练,没有仔细阅读官方的文档,参数的设置在网上搜了一个就直接套用,程序抛出了一个异常,提示No sufficient samples,就是我的-numPos参数写的是500,当时我的正样本只有300多个,然后就又加了200个样本,然后发现其实是参数设置的问题,,,

我的笔记本内存只有4G,,,,还经常出现内存分配不了的异常,,,,

 

设置完毕后就可以开始训练了,双击start_traing.bat开始训练!

技术分享

训练时间一般得几个小时吧,可以看看train.log看一看训练进度,,,

 

GetInfo.java代码

import java.awt.image.BufferedImage;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import javax.imageio.ImageIO;

public class GetInfo {

	public static void main(String[] args) {
		if(args.length<1){
			System.out.println("需要一个参数");
			System.out.println("比如 0722");
			System.out.println("生成到 E:\\training\\0722\\info.dat");
			return;
		}
		File info = new File("E:\\training\\"+args[0]+"\\info.dat");
		info.delete();
		if(!info.exists()){
			try {
				info.createNewFile();
			} catch (IOException e2) {
				e2.printStackTrace();
			}
		}
		FileWriter fileWritter=null;
		try {
			fileWritter = new FileWriter(info.getAbsolutePath(),true);
		} catch (IOException e1) {
			e1.printStackTrace();
		}
        BufferedWriter infoWritter = new BufferedWriter(fileWritter);

		String path = "E:\\training\\"+args[0]+"\\pos";
		File file = new File(path);
		File[] fileList = file.listFiles();

		BufferedImage bi = null;
		for(int i=0;i<fileList.length;i++){
			if(fileList[i].isFile()){

				try {
					bi = ImageIO.read(fileList[i]);
				} catch (IOException e) {
					e.printStackTrace();
				}
				int width = bi.getWidth();
				int height = bi.getHeight();
				try {
					infoWritter.write("pos/"+fileList[i].getName()+"  1  0  0 "+width+" "+height);
					infoWritter.newLine();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		try {
			infoWritter.flush();
			infoWritter.close();
		} catch (IOException e) {
			e.printStackTrace();
		}


	}
}


 

版权声明:本文为博主原创文章,未经博主允许不得转载。

目标检测程序开发(三)——级联分类器训练

标签:分类器训练   boosting   opencv   

原文地址:http://blog.csdn.net/giantpoplar/article/details/47030541

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!