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 网友周明才的博客。
基础学习笔记之opencv(3):haartraining生成.xml文件过程[转]
原文:https://www.cnblogs.com/Ph-one/p/11666267.html