训练工作主要分为如下几步:
加载训练环境
训练过程主要依靠OpenCV自带的两个可执行程序opencv_createsamples.exe和opencv_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/。下载的人脸数据如下所示:
按住ctrl+A全选,重命名第一张图像为(1),后面所有的图像会自动升序重命名,如下所示:
图片中还有白的背景头发等,训练人脸最好只有脸部,所以我先用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
生成的脸部图像如下所示:
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幅图片,负样本中不能含有人脸且数目必须要比正样本多,负样本尺寸不用归一化,截图如下所示:
获取样本路径列表
先进入正样本数据的目录下(posdata目录),新建一个文本文档posdir.txt,然后编辑文本如下:
编辑完成后退出保存,然后把文件扩展名修改为bat(dos系统批处理的文件格式),双击该文件,就会在该目录下生成一个posdata.txt,如下:
打开posdata.txt,使用文本编辑器的替换功能,做一些替换工作 。
替换1:将绝对路径替换成相对路径
替换2:1代表该图片中有几张人脸,后四个分别对应人脸起点坐标及宽和高
将替换好的posdata.txt复制到posdata目录的同级目录下。
同理,负样本的路径列表按照上述方法进行,替换时只需要将绝对路径改为相对路径即可,将替换好的negdata.txt复制到negdata目录的同级目录下。
生成正样本描述文件(.vec)
样本描述文件就是一个.vec文件,为opencv训练准备的,只有正样本需要,负样本不需要。 打开cmd.exe,强制进入到工作目录下用 cd /d 目录
查看opencv_createsamples.exe参数
其它参数不用填,默认就好,执行以下命令在cascadeTrain文件夹下就会生成一个posdata.vec的文件 。
训练人脸分类器
查看opencv_traincascade.exe参数
其它参数不用填,默认就好,执行以下命令进行训练,得到xml文件。
训练完成后,在haarxml文件夹下会生成各级的xml文件,如下所示:
使用分类器进行人脸检测
#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;
}
可看到最后一张检测不是很好,因为样本数据实在是太少了,就一两百个,实际应用中至少要训练个四五千个吧。我这里只是学习,考虑到训练时间就没训练那么多了。
参考文献:https://blog.csdn.net/aa512690069/article/details/17048999
https://blog.csdn.net/yangleo1987/article/details/52883864
https://blog.csdn.net/u010782875/article/details/78301638