opencv学习笔记五十三:训练自己的级联分类器

训练工作主要分为如下几步:

  • 加载训练环境
  • 制作训练数据集
  • 获取样本路径列表
  • 生成正样本描述文件(.vec)
  • 训练人脸分类器 
  • 使用分类器进行人脸检测

加载训练环境 

 训练过程主要依靠OpenCV自带的两个可执行程序opencv_createsamples.exeopencv_haartraining.exe操作完成的。新建一个文件夹命名为cascadeTrain,将opencv3.4.1\opencv\build\x64\vc14\bin中的上面两个可执行程序及两个dll文件拷到该文件夹下,如下图:

 

 

制作训练数据集

1、准备正样本:这里只是熟悉一下怎么训练自己感兴趣的东西,所以我还是进行简单的人脸训练,首先在网上下载了yale大学的人脸数据库,由耶鲁大学计算视觉与控制中心创建,包含15位志愿者的165张图片,包含光照,表情和姿态。下载网址为:http://vismod.media.mit.edu/vismod/classes/mas622-00/datasets/。下载的人脸数据如下所示:

opencv学习笔记五十三:训练自己的级联分类器_第1张图片

 按住ctrl+A全选,重命名第一张图像为(1),后面所有的图像会自动升序重命名,如下所示:

opencv学习笔记五十三:训练自己的级联分类器_第2张图片

 图片中还有白的背景头发等,训练人脸最好只有脸部,所以我先用matlab中的级联人脸检测将上述图片中的人脸检测出来,并统一尺寸为24*24的(opencv推荐的尺寸),然后保存为一组新的只包含脸部的图片,将其作为我们的正样本数据集。在cascadeTrain文件夹下新建posdata文件夹,将正样本数据集放入其中。

temp = 'C:\Users\Administrator\Desktop\cascadeTrain\';
for i = 1:165
    path1 = strcat(temp,'yalefaces\','(',num2str(i),')','.gif');
    I = imread(path1);    
    %人脸检测     
    faceDetector = vision.CascadeObjectDetector; 
    bboxes = step(faceDetector, I);
    I = imcrop(I,bboxes);%将检测到的人脸区域bboxes从原图中裁剪出来
    %尺寸归一化
    I = imresize(I,[24,24]);
    %将检测到的人脸图片另存为
    path2 = strcat(temp,'posdata\','(',num2str(i),')','.bmp');
    imwrite(I,path2);  
end

 生成的脸部图像如下所示:

opencv学习笔记五十三:训练自己的级联分类器_第3张图片

 

2、准备负样本:这里我采用的负样本是用的是weizmann团队网站上的图像分割数据库,里面有灰色图和彩色图,这里当然选取灰度图了。下载网址为http://www.wisdom.weizmann.ac.il/~vision/Seg_Evaluation_DB/dl.html。用matlab遍历出文件夹下所有灰度图作为负样本数据集。在cascadeTrain文件夹下新建negdata文件夹,将负样本数据集放入其中。

temp = 'C:\Users\Administrator\Desktop\cascadeTrain\';
for i = 1:200
    path1 = strcat(temp,'nonface\','(',num2str(i),')','\src_bw\');
    imgdir = dir([path1,'*.png']);%遍历该文件夹下所有png格式文件
    for j=1:length(imgdir)
        I = imread([path1,imgdir(j).name]);
        %另存为bmp格式
        path2 = strcat(temp,'negative\','(',num2str(i),')','.bmp');
        imwrite(I,path2);  
    end    
end

这里用了200幅图片,负样本中不能含有人脸且数目必须要比正样本多,负样本尺寸不用归一化,截图如下所示:

opencv学习笔记五十三:训练自己的级联分类器_第4张图片

 

 获取样本路径列表

先进入正样本数据的目录下(posdata目录),新建一个文本文档posdir.txt,然后编辑文本如下:

     编辑完成后退出保存,然后把文件扩展名修改为bat(dos系统批处理的文件格式),双击该文件,就会在该目录下生成一个posdata.txt,如下:

opencv学习笔记五十三:训练自己的级联分类器_第5张图片

 打开posdata.txt,使用文本编辑器的替换功能,做一些替换工作 。

 替换1:将绝对路径替换成相对路径

       opencv学习笔记五十三:训练自己的级联分类器_第6张图片

  

 替换2:1代表该图片中有几张人脸,后四个分别对应人脸起点坐标及宽和高

       opencv学习笔记五十三:训练自己的级联分类器_第7张图片

  将替换好的posdata.txt复制到posdata目录的同级目录下。

  同理,负样本的路径列表按照上述方法进行,替换时只需要将绝对路径改为相对路径即可,将替换好的negdata.txt复制到negdata目录的同级目录下。

 

生成正样本描述文件(.vec)

 样本描述文件就是一个.vec文件,为opencv训练准备的,只有正样本需要,负样本不需要。 打开cmd.exe,强制进入到工作目录下用 cd  /d  目录

opencv学习笔记五十三:训练自己的级联分类器_第8张图片

查看opencv_createsamples.exe参数

opencv学习笔记五十三:训练自己的级联分类器_第9张图片

  • -info 正样本路径列表,这里为-info posdata.txt
  • -vec 生成的vec文件名,这里取-vec posdata.vec
  • -bg  负样本路径列表,这里为-bg negdata.txt
  • -num 正样本数量,如实填写,我这里为-num  165  
  • -w -h 正样本的尺寸,它默认为-w 24 -h 24  

其它参数不用填,默认就好,执行以下命令在cascadeTrain文件夹下就会生成一个posdata.vec的文件 。

 

训练人脸分类器 

查看opencv_traincascade.exe参数

opencv学习笔记五十三:训练自己的级联分类器_第10张图片

 

  • -data:    先在cascadeTrain文件夹下创建一个haarxml的文件夹,将来生成的各级的xml文件都将在里面,-data haarxml
  • -vec:  刚才生成的样本描述文件,-vec posdata.vec
  • -numPos 用于训练的正样本数量,这里填的要比实际正样本少,因为每一级都可能有误分类,即将正样本当成负样本,则在下一级中该正样本就不能用了,所以要留点余量,-numPos 155
  • -numNeg 用于训练的负样本数量,这里可以比实际负样本大,它会自动从你负样本中不断地各种裁剪,-numNeg 600
  • -numStages 指定训练层数(决策树),推荐15~20,层数越多,错误率越低,耗时越长,-numStages 15
  • featureType 指定训练什么特征,LBP比HAAR快很多,精度稍低,这里训练haar特征,不用填,默认就好

其它参数不用填,默认就好,执行以下命令进行训练,得到xml文件。 

 训练完成后,在haarxml文件夹下会生成各级的xml文件,如下所示:

opencv学习笔记五十三:训练自己的级联分类器_第11张图片

 

使用分类器进行人脸检测

#include
using namespace cv;
using namespace std;

int main(int arc, char** argv) { 
	Mat src = imread("5.jpg");
	namedWindow("input", CV_WINDOW_AUTOSIZE);
	imshow("input", src);
	Mat gray;
	cvtColor(src, gray, CV_BGR2GRAY);
	CascadeClassifier faceclassifier;
	faceclassifier.load("C:/Users/Administrator/Desktop/cascadeTrain/lbpxml/cascade.xml");//加载训练好的xml文件
	
	vectorobjects;		
	faceclassifier.detectMultiScale(gray, objects, 1.1, 1, 0, Size(24, 24));
	for (int i = 0; i < objects.size(); i++) {
		rectangle(src, objects[i], Scalar(0, 255, 0), 2);
	}
	imshow("output", src);		
	waitKey(0);
	return 0;
}

 opencv学习笔记五十三:训练自己的级联分类器_第12张图片

opencv学习笔记五十三:训练自己的级联分类器_第13张图片

opencv学习笔记五十三:训练自己的级联分类器_第14张图片

可看到最后一张检测不是很好,因为样本数据实在是太少了,就一两百个,实际应用中至少要训练个四五千个吧。我这里只是学习,考虑到训练时间就没训练那么多了。

参考文献:https://blog.csdn.net/aa512690069/article/details/17048999

                    https://blog.csdn.net/yangleo1987/article/details/52883864

                    https://blog.csdn.net/u010782875/article/details/78301638

你可能感兴趣的:(opencv)