opencv中有两个函数可以训练分类器opencv_haartraining.exe和opencv_traincascade.exe,前者只能训练haar特征,后者可以用HAAR、LBP和HOG特征训练分类器。这两个函数都可以在opencv\build\x64\vc14\bin文件夹下找到。
1. 首先是样本的准备、其次是对样本进行处理、再次生成样本描述文件、最后一步是训练分类器。
2. 生成描述文件
正负样本都要转化成灰度图,本文采用的是识别海洋上航天的航空母舰,背景选择为大海,因为只是为了测试,这里选取了45张较少的正样本,77zhan张负样本。通过之前博客所介绍的方法进行统一灰度和尺度化(50*50)。
生成样本描述文件环节,如图所示首先在CMD中cd进入到当前目录,也就是opencv_createsamples.exe文件夹下;然后依次输入:opencv_createsamples.exe -info pos\pos.txt -vec pos.vec -bg neg\neg.txt -num 45 -w 50 -h 50 回车之后文件夹下就会出现pos.vec文件。只需要对正样本进行以上操作,负样本不需要生成vec文件。
注意pos.txt的格式如下:
0.jpg 1 0 0 50 50
1.jpg 1 0 0 50 50
2.jpg 1 0 0 50 50
3.jpg 1 0 0 50 50
4.jpg 1 0 0 50 50
5.jpg 1 0 0 50 50
3. 训练分类器
在以上准备工作都做好的情况下,就可以进行训练分类器了。opencv2.x应该是叫haartarining.exe opencv3.x将haar和lbp整合成一个。在cmd命令行下输入:C:\Users\wangz\Desktop\adboost>opencv_traincascade.exe -data cascade -vec pos.vec -bg neg\neg.txt -numpos 45 -numneg 77 -mem 80000000 -mode ALL -w 50 -h 50
参考:https://blog.csdn.net/nienelong3319/article/details/79287546
训练过程中发现一个问题,提示内存不足(可能是正样本数目不足),具体还未解决,但是过程是正确的,有知道问题的小伙伴希望交流一下。
最后就是训练出来的xml文件的使用了,具体如下:
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
String face_cascade_name = "D:/vcprojects/cascadetrain/custom_face_cascade.xml";
CascadeClassifier Detector;
String window_name = "Capture - Face detection";
int core=1 ;
int size_max = 10;
void callback(int, void*);
Mat image;
int main(int argc, char** argv) {
// 加载训练数据
if (!Detector.load(face_cascade_name)) {
printf("could not load face data...\n");
}
// 加载测试图片
Mat gray_src;
Mat image = imread("123.jpg");
namedWindow(window_name, CV_WINDOW_AUTOSIZE);
// 转换为灰度图像
createTrackbar("SIZE", window_name,&core, size_max,callback);
callback(0, 0);
imshow(window_name, image);
// 按任意键退出
waitKey(0);
return 0;
}
回调函数部分:
void callback(int, void*) {
Mat dimage;
blur(image, image, Size(2*core+1, 2 * core + 1), Point(-1, -1));
cvtColor(image, image, COLOR_BGR2GRAY);
equalizeHist(image, dimage);
// 使用自己训练的级联检测器人脸检测
//threshold(dimage, );
std::vector<Rect> faces;
Detector.detectMultiScale(dimage, faces, 1.3, 1, 0, Size(24, 24));
for (size_t t = 0; t < faces.size(); t++) {
rectangle(image, faces[t], Scalar(0, 0, 255), 3);
}
// 显示结果
}