OpenCV提供了两个程序可以训练自己的级联分类器opencv_haartraining与opencv_traincascade。opencv_traincascade是一个新程序,使用OpenCV 2.x API 以C++编写。这二者主要的区别是opencv_traincascade支持 Haar和 LBP (Local Binary Patterns)两种特征,并易于增加其他的特征。与Haar特征相比,LBP特征是整数特征,因此训练和检测过程都会比Haar特征快几倍。LBP和Haar特征用于检测的准确率,是依赖训练过程中的训练数据的质量和训练参数。训练一个与基于Haar特征同样准确度的LBP的分类器是可能的。
与其他分类器模型的训练方法类似,同样需要训练数据与测试数据;其中训练数据包含正样本pos与负样本neg。训练程序opencv_haartraining.exe与opencv_traincascade.exe对输入的数据格式是有要求的,所以需要相关的辅助程序:
opencv_createsamples 用来准备训练用的正样本数据和测试数据。opencv_createsamples 能够生成能被opencv_haartraining 和 opencv_traincascade 程序支持的正样本数据。它的输出为以 *.vec 为扩展名的文件,该文件以二进制方式存储图像。
所以opencv级联分类器训练与测试可分为以下四个步骤:
- 准备训练数据
- 训练级联分类器
- 测试分类器性能
- 利用训练好的分类器进行目标检测
1、准备训练数据
注:以行人数据为例,介绍分类器的训练
1.1准备正样本
正样本由opencv_createsamples生成。正样本可以由包含待检测物体的一张图片生成,也可由一系列标记好的图像生成。
首先将所有的正样本放在一个文件夹,如图所示1。其中,pos.dat文件为所有图像的列表文件,格式如图2所示:其中,第一列为图像名,第二列为该图像中正样本的个数,最后的为正样本在图像中的位置以及需要抠出的正样本的尺寸。pos.dat文件的生成方式:在dos窗口进入pos文件夹,输入dir /b > pos.dat ; 这样只能生成文件名列表,后面的正样本个数与位置尺寸还需手动添加。
图1.正样本数据
图2
1.2 opencv_createsamples.exe生成.vec格式的正样本文件
可以在dos命令窗运行opencv_createsamples.exe程序,也可利用.bat批处理文件;利用.bat批处理文件的格式如下。
"D:\Program Files\opencv\build\x64\vc10\bin\opencv_createsamples.exe" -info "pos\pos.dat" -vec pos.vec -num 500 -w 64 -h 128
pause
opencv_createsamples.exe程序的命令行参数:
- -info <collection_file_name> 描述物体所在图像以及大小位置的描述文件。
- -vec <vec_file_name>输出文件,内含用于训练的正样本。
- -img <image_file_name>输入图像文件名(例如一个公司的标志)。
- -bg<background_file_name>背景图像的描述文件,文件中包含一系列的图像文件名,这些图像将被随机选作物体的背景。
- -num<number_of_samples>生成的正样本的数目。
- -bgcolor<background_color>背景颜色(目前为灰度图);背景颜色表示透明颜色。因为图像压缩可造成颜色偏差,颜色的容差可以由-bgthresh指定。所有处于bgcolor-bgthresh和bgcolor+bgthresh之间的像素都被设置为透明像素。
- -bgthresh <background_color_threshold>
- -inv如果指定该标志,前景图像的颜色将翻转。
- -randinv如果指定该标志,颜色将随机地翻转。
- -maxidev<max_intensity_deviation>前景样本里像素的亮度梯度的最大值。
- -maxxangle <max_x_rotation_angle>X轴最大旋转角度,必须以弧度为单位。
- -maxyangle <max_y_rotation_angle>Y轴最大旋转角度,必须以弧度为单位。
- -maxzangle<max_z_rotation_angle>Z轴最大旋转角度,必须以弧度为单位。
- -show很有用的调试选项。如果指定该选项,每个样本都将被显示。如果按下Esc键,程序将继续创建样本但不再显示。
- -w <sample_width>输出样本的宽度(以像素为单位)。
- -h<sample_height>输出样本的高度(以像素为单位)。
1.3准备负样本
负样本可以是任意图像,但是这些图像中不能包含待检测的物体。用于抠取负样本的图像文件名被列在一个neg.dat文件中。生成方式与正样本相同,但仅仅包含文件名列表就可以了。这个文件是纯文本文件,每行是一个文件名(包括相对目录和文件名)这些图像可以是不同的尺寸,但是图像尺寸应该比训练窗口的尺寸大,因为这些图像将被用于抠取负样本,并将负样本缩小到训练窗口大小。如图3所示。
图3
2、训练级联分类器
OpenCV提供了两个可以训练的级联分类器的程序:opencv_haartraining与opencv_traincascade。opencv_haartraining是一个将被弃用的程序;opencv_traincascade是一个新程序。
opencv_traincascade程序的.bat批处理文件的格式如下:
"D:\Program Files\opencv\build\x64\vc10\bin\opencv_traincascade.exe" -data "E:\2013Mycode\TrainCascadeClassification" -vec pos.vec -bg neg\neg.dat -numPos 29 -numNeg 29 -numStages 20 -mem 200 -featureType LBP -w 64 -h 128
Pause
opencv_traincascade 的命令行参数如下所示:
1.通用参数:
- -data <cascade_dir_name>目录名,如不存在训练程序会创建它,用于存放训练好的分类器。
- -vec <vec_file_name>包含正样本的vec文件名(由opencv_createsamples程序生成)。
- -bg <background_file_name>背景描述文件,也就是包含负样本文件名的那个描述文件。
- -numPos <number_of_positive_samples>每级分类器训练时所用的正样本数目。
- -numNeg <number_of_negative_samples>每级分类器训练时所用的负样本数目,可以大于 -bg 指定的图片数目。
- -numStages <number_of_stages>训练的分类器的级数。
- -precalcValBufSize<precalculated_vals_buffer_size_in_Mb>缓存大小,用于存储预先计算的特征值(feature values),单位为MB。
- -precalcIdxBufSize<precalculated_idxs_buffer_size_in_Mb>缓存大小,用于存储预先计算的特征索引(feature indices),单位为MB。内存越大,训练时间越短。
- -baseFormatSave这个参数仅在使用Haar特征时有效。如果指定这个参数,那么级联分类器将以老的格式存储。
2.级联参数:
- -stageType <BOOST(default)>级别(stage)参数。目前只支持将BOOST分类器作为级别的类型。
- -featureType<{HAAR(default), LBP}>特征的类型: HAAR - 类Haar特征; LBP - 局部纹理模式特征。
- -w <sampleWidth>
- -h <sampleHeight>训练样本的尺寸(单位为像素)。必须跟训练样本创建(使用 opencv_createsamples 程序创建)时的尺寸保持一致。
3.分类器参数:
- -bt <{DAB, RAB, LB,GAB(default)}> Boosted分类器参数:
- DAB - Discrete AdaBoost, RAB - Real AdaBoost, LB - LogitBoost, GAB -Gentle AdaBoost。Boosted分类器的类型:
- -minHitRate<min_hit_rate>分类器的每一级希望得到的最小检测率。总的检测率大约为 min_hit_rate^number_of_stages。
- -maxFalseAlarmRate<max_false_alarm_rate>分类器的每一级希望得到的最大误检率。总的误检率大约为 max_false_alarm_rate^number_of_stages.
- -weightTrimRate <weight_trim_rate>
- Specifies whether trimmingshould be used and its weight.一个还不错的数值是0.95。
- -maxDepth <max_depth_of_weak_tree>弱分类器树最大的深度。一个还不错的数值是1,是二叉树(stumps)。
- -maxWeakCount<max_weak_tree_count>每一级中的弱分类器的最大数目。The boostedclassifier (stage) will have so many weak trees (<=maxWeakCount), as neededto achieve the given -maxFalseAlarmRate.
4.类Haar特征参数:
- -mode <BASIC (default) |CORE | ALL>选择训练过程中使用的Haar特征的类型。 BASIC 只使用右上特征, ALL使用所有右上特征和45度旋转特征。
5.LBP特征参数:
LBP特征无参数。
3.测试分类器性能
3.1 opencv_haartraining程序训练一个分类器模型
opencv_haartraining程序的.bat批处理文件的格式如下:
"D:\Program Files\opencv\build\x64\vc10\bin\opencv_haartraining.exe" -data "E:\2013Mycode\TrainCascadeClassification\cascade" -vec pos.vec -bg neg\neg.dat -npos 29 -nneg 29 -mem 200 -mode BASIC -w 64 -h 128
Pause
opencv_haartraining 的命令行参数如下:
- -data<dir_name>存放训练好的分类器的路径名。
- -vec<vec_file_name>正样本文件名(由trainingssamples程序或者由其他的方法创建的)
- -bg<background_file_name>背景描述文件。
- -npos<number_of_positive_samples>,
- -nneg<number_of_negative_samples>用来训练每一个分类器阶段的正/负样本。合理的值是:nPos = 7000;nNeg= 3000
- -nstages<number_of_stages>训练的阶段数。
- -nsplits<number_of_splits>决定用于阶段分类器的弱分类器。如果1,则一个简单的stump classifier被使用。如果是2或者更多,则带有number_of_splits个内部节点的CART分类器被使用。
- -mem<memory_in_MB>预先计算的以MB为单位的可用内存。内存越大则训练的速度越快。
- -sym(default)
- -nonsym指定训练的目标对象是否垂直对称。垂直对称提高目标的训练速度。例如,正面部是垂直对称的。
- -minhitrate《min_hit_rate》每个阶段分类器需要的最小的命中率。总的命中率为min_hit_rate的number_of_stages次方。
- -maxfalsealarm<max_false_alarm_rate>没有阶段分类器的最大错误报警率。总的错误警告率为max_false_alarm_rate的number_of_stages次方。
- -weighttrimming<weight_trimming>指定是否使用权修正和使用多大的权修正。一个基本的选择是0.9
- -eqw
- -mode<basic(default)|core|all>选择用来训练的haar特征集的种类。basic仅仅使用垂直特征。all使用垂直和45度角旋转特征。
- -w《sample_width》
- -h《sample_height》训练样本的尺寸,(以像素为单位)。必须和训练样本创建的尺寸相同。
3.2 opencv_performance测试分类器模型
opencv_performance程序的.bat批处理文件的格式如下:
"D:\Program Files\opencv\build\x64\vc10\bin\opencv_performance.exe" -data "E:\2013Mycode\TrainCascadeClassification\cascade.xml" -info test/test.dat -w 64 -h 128 -rs 30
Pause
opencv_performance 的命令行参数如下所示:
- -data <classifier_directory_name>训练好的分类器
- -info <collection_file_name> 描述物体所在图像以及大小位置的描述文件
- -maxSizeDiff <max_size_difference =1.500000>
- -maxPosDiff <max_position_difference =0.300000>
- -sf <scale_factor = 1.200000>
- -ni 选项抑制创建的图像文件的检测
- -nos <number_of_stages = -1>
- -rs <roc_size = 40>]
- -w <sample_width = 24>
- -h <sample_height = 24>
4、利用训练好的分类器进行目标检测
#include "opencv2/core/core.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <fstream>
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
string Cascade_mode ="cascade.xml"; //已训练好的分类器
CascadeClassifier Mycascade;
string window_name = "Pedestrain";
Mat detectAndDisplay( Mat);
int main()
{
Mat image,ROI;
if(!Mycascade.load( Cascade_mode )) { printf("[error] 无法加载级联分类器文件!\n"); return -1; }
image= imread("walk.jpg");//读取图片
if(!image.data) { printf("[error] 没有图片\n"); return -5; }
ROI= detectAndDisplay(image);
waitKey(0);
return 4;
}
Mat detectAndDisplay( Mat frame)
{
std::vector<Rect> pedestrain;
Mat frame_gray(frame.size(),CV_8U);
cvtColor( frame, frame_gray, CV_BGR2GRAY );
equalizeHist( frame_gray, frame_gray );
Mycascade.detectMultiScale( frame_gray, pedestrain, 1.1, 2, 0, Size(64, 128) );
for( int i = 0; i < pedestrain.size(); i++ ) {
rectangle(frame, //图像.
pedestrain[i],
Scalar(0, 255, 0), //线条颜色 (RGB) 或亮度(灰度图像 )(grayscale image)
1); //组成矩形的线条的粗细程度。取负值时(如 CV_FILLED)函数绘制填充了色彩的矩形
}
imshow( window_name, frame );
return frame;
}
运行结果如图4:
更多资源:http://blog.csdn.net/wuxiaoyao12/article/details/39227189
http://note.sonots.com/SciSoftware/haartraining.html#x15ebd98
http://www.cnblogs.com/easymind223/archive/2012/07/03/2574826.html
http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/user_guide/ug_traincascade.html