Notes of opencv based learning (3): haartraining .xml file generation process [rpm]

1. Prepare positive and negative samples:

     In the last lecture http://www.cnblogs.com/tornadomeet/archive/2012/03/27/2420088.html  , we have collected a positive sample used for training. Here we began collecting samples of negative, negative sample requirements are: must not contain a human face, and the picture size is not required normalized to a positive sample size, sample size being just larger than or equal to. We recommend negative samples with grayscale, speed up the training, and the negative sample must not be repeated, to increase the diversity of the negative samples.

     Here I used the negative samples using a weizmann team http://www.wisdom.weizmann.ac.il/~vision/Seg_Evaluation_DB/dl.html  image segmentation database on the site, which has a gray chart and color chart, here of course, selecting the greyscale.

     With a total of 200 pictures, about the size of 300 * 200 pixels, the screenshot shown below:

     These can be seen more than 200 photos basic no one face, so that should be possible.

     Pictures of positive and negative samples are ready, start making positive and negative samples following description files.

     First, establish a good folder and copy the picture is good, as follows:

    

     Pos_image is loaded in the positive samples, neg_image into a negative sample, test_image placed in the test sample. And later to use the two tools .exe files are copied (in opencv installation directory C: \ Program Files opencv2.3.1 \ \ \ x86 under the \ build common).

2. The positive and negative samples generated profile:

     Establish a positive profile of the sample:

     Open cmd window, enter pos_img file folder location on the map, you can see the folder image shows the following:

     

     Use the command dir / b> pos_image.txt. as the picture shows

     

    且用editplus打开该文件,删除最后一行,最后将名字归一化如下所示:

     其中的pos_image/是相对路径名,后面紧接着的是文件名,1代表一个文件,0 0 24 24表示这个文件的2个顶点位置坐标。保存退出即ok!

负样本的描述文件类似,只是不需要考虑其大小位置。

     也是进入neg_imgae后在cmd内使用命令dir /b >neg_image.txt,如图所示:

     

     同样删除最后一行文字,且将文件相对路径加入如下所示:

  

 

     至此,训练数据准备完备了。

3.创建vec文件:

     在创建vec文件时,需要把pos_image.txt和neg_image.txt两个样本描述文件剪切到上一目录,如图所示:

     然后利用opencv_createsamples.exe应用程序在该目录下使用如下cmd命令:

    

     其中的-vec是指定后面输出vec文件的文件名,-info指定正样本描述文件,-bg指定负样本描述文件,-w和-h分别指正样本的宽和高,-num表示正样本的个数。执行完该命令后就会在当前目录下生产一个pos.vec文件了

4.使用opencv_haartraining.exe文件进行训练

     首先在当前目录下新建一个xml文件夹用于存放生成的.xml文件。

     在当前目录使用cmd命令:

     Opcnv_haartraining.exe –data xml –vec pos.vec –bg neg_image.txt –nsplits 1 –sym –w 24 –h 24 –mode all –mem 1280

截图如下:

     

     其中-data为输出xml中间文件的位置,-sym表示训练的目标为垂直对称,-nsplits 1表示使用简单的stump classfier分类。-mem 1280 表示允许使用计算机的1280M内存,-mode all 表示使用haar特征集的种类既有垂直的,又有45度角旋转的。

     因为数据量不是很多,不到半个钟头就训练好了。在当前目录下生产了一个xml.xml文件,将其重名名为face_test.xml。

5.实验结果:

     利用上面训练出来的face_test.xml文件来检测下人脸,首先来一张比较正面的人脸图,用奥巴马的,检测结果如下:

     

     为了看看是否不是特别正的,且有背景干扰的结果,用了lena的图,检测结果如下:

     

 

 

     上面说明其效果还是不错的。其测试源码和前面的博客http://www.cnblogs.com/tornadomeet/archive/2012/03/22/2411318.html的代码类似,删减了人眼检测的代码而已,源码如下:

 1 // face_detect.cpp : 定义控制台应用程序的入口点。
 2 //
 3 #include "stdafx.h"
 4 
 5 #include "opencv2/objdetect/objdetect.hpp"
 6 #include "opencv2/highgui/highgui.hpp"
 7 #include "opencv2/imgproc/imgproc.hpp"
 8 #include "opencv2/ml/ml.hpp"
 9 
10 #include <iostream>
11 #include <stdio.h>
12 
13 using namespace std;
14 using namespace cv;
15 
16 void detectAndDraw( Mat& img,
17                    CascadeClassifier& cascade, 
18                    double scale);
19 
20 String cascadeName = "./face_test.xml";//人脸的训练数据
21 
22 int main( int argc, const char** argv )
23 {
24     Mat image;
25     CascadeClassifier cascade, nestedCascade;//创建级联分类器对象
26     double scale = 1.3;
27 //    image = imread("obama_gray.bmp",1);
28     image = imread("lena_gray.jpg",1);
29     namedWindow( "result", 1 );//opencv2.0以后用namedWindow函数会自动销毁窗口
30 
31     if( !cascade.load( cascadeName ) )//从指定的文件目录中加载级联分类器
32     {
33          cerr << "ERROR: Could not load classifier cascade" << endl;
34          return 0;
35     }
36 
37     if( !image.empty() )//读取图片数据不能为空
38     {
39         detectAndDraw( image, cascade, scale );
40         waitKey(0);
41     }
42 
43     return 0;
44 }
45 
46 void detectAndDraw( Mat& img,
47                    CascadeClassifier& cascade, 
48                    double scale)
49 {
50     int i = 0;
51     double t = 0;
52     vector<Rect> faces;
53     const static Scalar colors[] =  { CV_RGB(0,0,255),
54         CV_RGB(0,128,255),
55         CV_RGB(0,255,255),
56         CV_RGB(0,255,0),
57         CV_RGB(255,128,0),
58         CV_RGB(255,255,0),
59         CV_RGB(255,0,0),
60         CV_RGB(255,0,255)} ;//用不同的颜色表示不同的人脸
61 
62     Mat gray, smallImg( cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 );//将图片缩小,加快检测速度
63 
64     cvtColor( img, gray, CV_BGR2GRAY );//因为用的是类haar特征,所以都是基于灰度图像的,这里要转换成灰度图像
65     resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR );//将尺寸缩小到1/scale,用线性插值
66     equalizeHist( smallImg, smallImg );//直方图均衡
67 
68     t = (double)cvGetTickCount();//用来计算算法执行时间
69 
70 //检测人脸
71 //detectMultiScale函数中smallImg表示的是要检测的输入图像为smallImg,faces表示检测到的人脸目标序列,1.1表示
72 //每次图像尺寸减小的比例为1.1,2表示每一个候选矩形需要记录2个邻居,CV_HAAR_SCALE_IMAGE表示使用haar特征,Size(30, 30)
73 //为目标的最小最大尺寸
74     cascade.detectMultiScale( smallImg, faces,
75         1.1, 2, 0
76         //|CV_HAAR_FIND_BIGGEST_OBJECT
77 //|CV_HAAR_DO_ROUGH_SEARCH
78         |CV_HAAR_SCALE_IMAGE
79         ,
80         Size(30, 30) );
81 
82     t = (double)cvGetTickCount() - t;//相减为算法执行的时间
83     printf( "detection time = %g ms\n", t/((double)cvGetTickFrequency()*1000.) );
84     for( vector<Rect>::const_iterator r = faces.begin(); r != faces.end(); r++, i++ )
85     {
86         Mat smallImgROI;
87         vector<Rect> nestedObjects;
88         Point center;
89         Scalar color = colors[i%8];
90         int radius;
91         center.x = cvRound((r->x + r->width*0.5)*scale);//还原成原来的大小
92         center.y = cvRound((r->y + r->height*0.5)*scale);
93         radius = cvRound((r->width + r->height)*0.25*scale);
94         circle( img, center, radius, color, 3, 8, 0 );
95         smallImgROI = smallImg(*r);
96     }
97     cv::imshow( "result", img );
98 }

6.参考文献:

1. http://hi.baidu.com/zdd007007/blog/item/b2e7f026eec9e23f8644f959.html 的博客。

2. http://blog.csdn.net/guxj821/article/details/6341239 网友周明才的博客。

 

 

 

作者:tornadomeet 出处:http://www.cnblogs.com/tornadomeet 欢迎转载或分享,但请务必声明文章出处。 (新浪微博:tornadomeet,欢迎交流!)
 
分类:  OpenCV

1.准备正负样本:

     在上一讲http://www.cnblogs.com/tornadomeet/archive/2012/03/27/2420088.html 中,我们已经收集到了训练所用的正样本。下面就开始收集负样本了,负样本要求是:不能包含人脸,且图片大小也不需要归一化到正样本尺寸,只需比正样本尺寸大或者相等即可。建议负样本用灰度图,加快训练速度,且负样本一定不能重复,要增大负样本的差异性。

     这里我采用的负样本是用的是weizmann团队http://www.wisdom.weizmann.ac.il/~vision/Seg_Evaluation_DB/dl.html 网站上的图像分割数据库,里面有灰色图和彩色图,这里当然选取灰度图了。

     总共用了200幅图片,大小大约在300*200像素,截图如下所示:

     可以看出这些200多张图片基本都没有人脸,所以说应该是可以的。

     正负样本的图片准备好了,下面就开始制作正负样本的描述文件了。

     首先建立好文件夹,把图片拷贝好,如下所示:

    

     Pos_image中放入的是正样本,neg_image放入的是负样本,test_image放入的是测试样本。并将后面要用到的2个工具.exe文件也拷贝过来(在opencv的安装目录C:\Program Files\opencv2.3.1\build\common\x86下)。

2.生成正负样本描述文件:

     建立正样本的描述文件:

     打开cmd窗口,进入上图所在pos_img文件夹内,可以看到此文件夹图片显示如下:

     

     使用命令dir /b >pos_image.txt。如图所示

     

    且用editplus打开该文件,删除最后一行,最后将名字归一化如下所示:

     其中的pos_image/是相对路径名,后面紧接着的是文件名,1代表一个文件,0 0 24 24表示这个文件的2个顶点位置坐标。保存退出即ok!

负样本的描述文件类似,只是不需要考虑其大小位置。

     也是进入neg_imgae后在cmd内使用命令dir /b >neg_image.txt,如图所示:

     

     同样删除最后一行文字,且将文件相对路径加入如下所示:

  

 

     至此,训练数据准备完备了。

3.创建vec文件:

     在创建vec文件时,需要把pos_image.txt和neg_image.txt两个样本描述文件剪切到上一目录,如图所示:

     然后利用opencv_createsamples.exe应用程序在该目录下使用如下cmd命令:

    

     其中的-vec是指定后面输出vec文件的文件名,-info指定正样本描述文件,-bg指定负样本描述文件,-w和-h分别指正样本的宽和高,-num表示正样本的个数。执行完该命令后就会在当前目录下生产一个pos.vec文件了

4.使用opencv_haartraining.exe文件进行训练

     首先在当前目录下新建一个xml文件夹用于存放生成的.xml文件。

     在当前目录使用cmd命令:

     Opcnv_haartraining.exe –data xml –vec pos.vec –bg neg_image.txt –nsplits 1 –sym –w 24 –h 24 –mode all –mem 1280

截图如下:

     

     其中-data为输出xml中间文件的位置,-sym表示训练的目标为垂直对称,-nsplits 1表示使用简单的stump classfier分类。-mem 1280 表示允许使用计算机的1280M内存,-mode all 表示使用haar特征集的种类既有垂直的,又有45度角旋转的。

     因为数据量不是很多,不到半个钟头就训练好了。在当前目录下生产了一个xml.xml文件,将其重名名为face_test.xml。

5.实验结果:

     利用上面训练出来的face_test.xml文件来检测下人脸,首先来一张比较正面的人脸图,用奥巴马的,检测结果如下:

     

     为了看看是否不是特别正的,且有背景干扰的结果,用了lena的图,检测结果如下:

     

 

 

     上面说明其效果还是不错的。其测试源码和前面的博客http://www.cnblogs.com/tornadomeet/archive/2012/03/22/2411318.html的代码类似,删减了人眼检测的代码而已,源码如下:

 1 // face_detect.cpp : 定义控制台应用程序的入口点。
 2 //
 3 #include "stdafx.h"
 4 
 5 #include "opencv2/objdetect/objdetect.hpp"
 6 #include "opencv2/highgui/highgui.hpp"
 7 #include "opencv2/imgproc/imgproc.hpp"
 8 #include "opencv2/ml/ml.hpp"
 9 
10 #include <iostream>
11 #include <stdio.h>
12 
13 using namespace std;
14 using namespace cv;
15 
16 void detectAndDraw( Mat& img,
17                    CascadeClassifier& cascade, 
18                    double scale);
19 
20 String cascadeName = "./face_test.xml";//人脸的训练数据
21 
22 int main( int argc, const char** argv )
23 {
24     Mat image;
25     CascadeClassifier cascade, nestedCascade;//创建级联分类器对象
26     double scale = 1.3;
27 //    image = imread("obama_gray.bmp",1);
28     image = imread("lena_gray.jpg",1);
29     namedWindow( "result", 1 );//opencv2.0以后用namedWindow函数会自动销毁窗口
30 
31     if( !cascade.load( cascadeName ) )//从指定的文件目录中加载级联分类器
32     {
33          cerr << "ERROR: Could not load classifier cascade" << endl;
34          return 0;
35     }
36 
37     if( !image.empty() )//读取图片数据不能为空
38     {
39         detectAndDraw( image, cascade, scale );
40         waitKey(0);
41     }
42 
43     return 0;
44 }
45 
46 void detectAndDraw( Mat& img,
47                    CascadeClassifier& cascade, 
48                    double scale)
49 {
50     int i = 0;
51     double t = 0;
52     vector<Rect> faces;
53     const static Scalar colors[] =  { CV_RGB(0,0,255),
54         CV_RGB(0,128,255),
55         CV_RGB(0,255,255),
56         CV_RGB(0,255,0),
57         CV_RGB(255,128,0),
58         CV_RGB(255,255,0),
59         CV_RGB(255,0,0),
60         CV_RGB(255,0,255)} ;//用不同的颜色表示不同的人脸
61 
62     Mat gray, smallImg( cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 );//将图片缩小,加快检测速度
63 
64     cvtColor( img, gray, CV_BGR2GRAY );//因为用的是类haar特征,所以都是基于灰度图像的,这里要转换成灰度图像
65     resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR );//将尺寸缩小到1/scale,用线性插值
66     equalizeHist( smallImg, smallImg );//直方图均衡
67 
68     t = (double)cvGetTickCount();//用来计算算法执行时间
69 
70 //检测人脸
71 //detectMultiScale函数中smallImg表示的是要检测的输入图像为smallImg,faces表示检测到的人脸目标序列,1.1表示
72 //每次图像尺寸减小的比例为1.1,2表示每一个候选矩形需要记录2个邻居,CV_HAAR_SCALE_IMAGE表示使用haar特征,Size(30, 30)
73 //为目标的最小最大尺寸
74     cascade.detectMultiScale( smallImg, faces,
75         1.1, 2, 0
76         //|CV_HAAR_FIND_BIGGEST_OBJECT
77 //|CV_HAAR_DO_ROUGH_SEARCH
78         |CV_HAAR_SCALE_IMAGE
79         ,
80         Size(30, 30) );
81 
82     t = (double)cvGetTickCount() - t;//相减为算法执行的时间
83     printf( "detection time = %g ms\n", t/((double)cvGetTickFrequency()*1000.) );
84     for( vector<Rect>::const_iterator r = faces.begin(); r != faces.end(); r++, i++ )
85     {
86         Mat smallImgROI;
87         vector<Rect> nestedObjects;
88         Point center;
89         Scalar color = colors[i%8];
90         int radius;
91         center.x = cvRound((r->x + r->width*0.5)*scale);//还原成原来的大小
92         center.y = cvRound((r->y + r->height*0.5)*scale);
93         radius = cvRound((r->width + r->height)*0.25*scale);
94         circle( img, center, radius, color, 3, 8, 0 );
95         smallImgROI = smallImg(*r);
96     }
97     cv::imshow( "result", img );
98 }

6.参考文献:

1. http://hi.baidu.com/zdd007007/blog/item/b2e7f026eec9e23f8644f959.html 的博客。

2. http://blog.csdn.net/guxj821/article/details/6341239 网友周明才的博客。

 

 

 

Guess you like

Origin www.cnblogs.com/Ph-one/p/11666267.html