如何训练一个分类器来识别某个目标(opencv3版本)

训练分类器主要分为四个阶段。
一、收集目标样本并创建一个正样本的.dat文件。
将我们希望得到的目标的示例(如:人脸的前向视图,汽车的侧向视图等)存储在一个或多个目录下,使用如下集合描述文件形式的文本文件引索:

<path>/<img_name_1> <count_1> <x11> <y11> <w11> <h11> <x12> <y12> ...
<path>/<img_name_2> <count_2> <x21> <y21> <w21> <h21> <x22> <y22> ...
...

每一行包含目标所在图像的路径(如果存在)和文件名(建议只用保存图像文件名就可以了)。count_x为存在于图像中目标的数量。其后是一列包含目标的矩形,包括矩形的左上角的x坐标和y坐标,然后是以像素为单位的宽度和高度。
例如,我们有一组人脸检测的数据集位于目录data/faces/,那么集合描述文件faces.dat如下所示:

data/faces/image1.jpg 2 73 100 25 37 133 123 30 45
data/faces/image2.jpg 1 155 200 55 78
....

对于正负样本的.dat文件的创建,我自己写了个exe程序来简便这个过程,有需要的可以去这里:dat文件创建程序下载。如果想要查看dat文件里面的内容,可以把后缀dat改为txt查看。程序的大致功能如下图:
软件运行界面
二、使用opencv自带的程序opencv_createsamples创建一个正样本的“矢量”输出文件。
opencv_createsamples.exe文件存放路径为:…\opencv\build\x64\vc15\bin。你可以将这个文件拷贝到你样本存放路径的上一级路径。
接下来使用命令行来运行这个程序:
1、使用【win】+【R】键调出搜索界面,输入cmd调出命令行界面。
2、假设opencv_createsamples.exe文件放在桌面;首先用cd命令将当前位置切换到桌面:cd C:\Users\lcp\Desktop
3、开始创建.vec文件。如输入如下命令:opencv_createsamples -info faces.dat -vec faces.vec -w 30 -h 40
关于opencv_createsamples的参数的详细说明请看这里:参数的详细说明
三、创建负样本的.dat文件。负样本可以为任何不包含感兴趣目标的图像。例如,生成一个图象集合文件为background.dat,其内容包括图像的路径和文件名,如下所示:

data/vacations/beach.jpg
data/nonfaces/img_043.jpg
data/nonfaces/dadad.jpg

同正样本的.dat文件的创建,也可以使用步骤一中的我所说的程序来快捷创建。
四、使用opencv_traincascade.exe来训练级联器。
这个文件的位置同opencv_creatasamples.exe文件,也需要使用命令行来使用。命令示例如下所示,目的是创建一个名为cahua.xml的训练级联:opencv_traincascade -data cahua.xml -vec data/samples/cahua.vec -bg background.dat -numPos 1000 -numNeg 5000 -featureType LBP -w 20 -h 20 -minHitRate 0.998 -maxFalseAlarmRate 0.5 -mode ALL
这个文件的参数的详细说明在这里:参数的详细说明可见。
如果在使用这两个程序时遇见问题,部分问题及解决办法见这里

五、训练出的xml文件的使用方法如下面的程序所示:

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/opencv.hpp> 
#include <vector>
#include <cstdio> 

using namespace std;
using namespace cv; 

int main(){		
	cv::namedWindow("识别图", cv::WINDOW_GUI_EXPANDED);
	// 【1】加载分类器	
	CascadeClassifier cascade;	
	cascade.load("cascade2.xml"); 	
	Mat srcImage, grayImage,dstImage;	
	// 【2】读取图片	
	srcImage = imread("test.jpg");	
	dstImage = srcImage.clone();	
	//imshow("【原图】", srcImage); 	
	grayImage.create(srcImage.size(), srcImage.type());	
	cvtColor(srcImage, grayImage, CV_BGR2GRAY); // 生成灰度图,提高检测效率 	
	// 定义7种颜色,用于标记目标	
	Scalar colors[] =	{		
		// 红橙黄绿青蓝紫		
		CV_RGB(255, 0, 0),		
		CV_RGB(255, 97, 0),		
		CV_RGB(255, 255, 0),		
		CV_RGB(0, 255, 0),		
		CV_RGB(0, 255, 255),		
		CV_RGB(0, 0, 255),		
		CV_RGB(160, 32, 240)	
	}; 	
	// 【3】检测	
	vector<Rect> rect;	
	cascade.detectMultiScale(srcImage, rect, 1.1, 3, 0);
	// 分类器对象调用 	
	printf("检测到目标个数:%d\n", rect.size()); 	
	// 【4】标记出识别到的目标区域	
	for (int i = 0; i < rect.size();i++)	
	{		
		cv::rectangle(dstImage, rect[i], colors[0], 10, 80, 0);
	} 	
	// 【5】显示	
	imshow("识别图", dstImage);		
	waitKey(0);
	return 0;
}

如果出现[ INFO:0] Initialize OpenCL runtime…这句话后面没反应的话,多等待一会,可能识别到的目标有点多。

猜你喜欢

转载自blog.csdn.net/qq_34463441/article/details/83214974