当前位置:   article > 正文

基于opencv训练haar特征生成xml分类_haar分类器xml文件

haar分类器xml文件

一、训练

1.1 准备数据

数据分为正样本和负样本:正样本是要识别的部分,负样本是不包含要识别的部分。

正样本要求尽量转成灰度图,统一大小尺寸,数据量在1000张图像以上;负样本之间的尺寸大小随意,数据量尽量是正样本的3倍。

以车辆检测为例,下图为正样本的示例:
在这里插入图片描述
下图为负样本的示例:
在这里插入图片描述

1.2 创建txt描述文件

为正样本创建描述文件posdata.txt,负样本创建描述文件negdata.txt文件:

#include <io.h>
#include <vector>
#include "opencv2/opencv.hpp"
#include <fstream>

using namespace cv;
using namespace std;

void getFiles(string path, vector<string>& files, vector<string>& ownname)
{
	intptr_t hFile = 0;
	struct _finddata_t fileinfo;
	string p;
	if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1)
	{
		do
		{
			if ((fileinfo.attrib &  _A_SUBDIR))
			{
				if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
					getFiles(p.assign(path).append("\\").append(fileinfo.name), files, ownname);
			}
			else
			{
				files.push_back(p.assign(path).append("\\").append(fileinfo.name));
				ownname.push_back(fileinfo.name);
			}
		} while (_findnext(hFile, &fileinfo) == 0);
		_findclose(hFile);
	}
}

void get_txt()
{
	vector<string> files_pos, names_pos;
	getFiles("E://vs_program//Haar_test//train_car//posdata", files_pos, names_pos);  //正样本的路径

	vector<string> files_neg, names_neg;
	getFiles("E://vs_program//Haar_test//train_car//negdata", files_neg, names_neg);  //负样本的路径

	ofstream pxData;
	pxData.open("..//train_car//posdata.txt", std::ios::out | std::ios::trunc);  //在train_car文件夹下生成正样本的txt文件
	for (int i = 0; i < files_pos.size(); i++)
	{
		pxData << files_pos[i] << " 1 0 0 32 24" << std::endl;  //32*24是resize正样本的尺寸
	}
	pxData.close();

	pxData.open("..//train_car//negdata.txt", std::ios::out | std::ios::trunc);  //在train_car文件夹下生成负样本的txt文件
	for (int i = 0; i < files_neg.size(); i++)
	{
		pxData << files_neg[i] << std::endl;
	}
	pxData.close();
}

int main()
{
	get_txt();
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61

1.3 编译opencv

编译的主要步骤可见QT配置opencv并打包发布
通过上述的编译,在bin文件夹中便得到opencv_createsamples.exe,但还需要opencv_traincascade.exe,因此,在Search里面输入MOD,添加OPENCV_EXTRA_MODULES_PATH值,即在Value处填入opencv_contrib路径下modules文件夹的路径,如下图
在这里插入图片描述
注意:路径是反斜杠,否则会报错【CMake Error at cmake/OpenCVModule.cmake:288 (message): No modules has been found:】。

改好之后再次点击Configure,出现configure done之后点击Generate,最后应该是下图这样的:
在这里插入图片描述
至此,便得到opencv_traincascade.exe。

1.4 训练

1.4.1 使用opencv_createsamples.exe创建样本

在cmd里cd到编译后的文件夹下,再将两个txt拷贝至此,运行如下语句:

opencv_createsamples.exe -info posdata.txt -vec detect_number.vec -bg negdata.txt -num 850 -w 32 -h 24
  • 1

参数解释:
-info:posdata.txt的位置,可以直接使用绝对地址避免出错
-vec 生成vec文件的位置和名称
-bg negdata.txt的位置,可以直接使用绝对地址
-num 正样本的数量
-w -h 正样本的宽高

1.4.2 使用opencv_traincascade.exe开始训练

在程序所在的上一个文件夹中,新建一个文件夹xml_file。不能在当前文件夹下新建,否则会报错【terminate called after throwing an instance of ‘cv::Exception‘,已放弃 (核心已转储)】。

再运行如下语句:

opencv_traincascade.exe -data ../xml_file -vec detect_number.vec -bg negdata.txt -numPos 850 -numNeg 4666 -numStages 20 -featureType HAAR -w 32 -h 24
  • 1

参数解释:
-data 存放训练好的xml文件的文件夹,这个一定要事先创建好
-vec 之前生成vec文件
-bg negdata.txt的位置
-numPos 正样本的数量
-numNeg 负样本的数量
-numStages 训练步数
-featureType 特征类型,有三种,HAAR最常用
-w -h 正样本的宽高

开始训练后如图:
在这里插入图片描述
训练完成后在xml_file文件夹里会生成一系列xml文件,最后能用的文件是cascade.xml

二、测试

#include <io.h>
#include <vector>
#include "opencv2/opencv.hpp"
#include <fstream>

using namespace cv;
using namespace std;

void getFiles(string path, vector<string>& files, vector<string>& ownname)
{
	intptr_t hFile = 0;
	struct _finddata_t fileinfo;
	string p;
	if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1)
	{
		do
		{
			if ((fileinfo.attrib &  _A_SUBDIR))
			{
				if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
					getFiles(p.assign(path).append("\\").append(fileinfo.name), files, ownname);
			}
			else
			{
				files.push_back(p.assign(path).append("\\").append(fileinfo.name));
				ownname.push_back(fileinfo.name);
			}
		} while (_findnext(hFile, &fileinfo) == 0);
		_findclose(hFile);
	}
}

int main()
{
	vector<string> files, names;
	getFiles("..//train_car//test", files, names);
	CascadeClassifier face_cascade;
	String file1 = "..//carTrain3//traincascade//cascade05022.xml";
	if (!face_cascade.load(file1))
	{
		printf("can not load the file... xml\n");
		return -1;
	}

	for (int j = 0; j < files.size(); j++)
	{
		Mat image = imread(files[j]);
		resize(image, image, Size(400, 200));
		vector<Rect> objects;
		Mat gray_image;
		cvtColor(image, gray_image, COLOR_BGR2GRAY);
		face_cascade.detectMultiScale(gray_image, objects, 1.1, 2, 0 | CASCADE_SCALE_IMAGE, Size(1, 1));

		vector<Rect> pick = NMS(objects, 0.1);
		//框选出脸部区域
		for (int i = 0; i < pick.size(); i++)
		{
			RNG rng(i);
			Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), 20);
			rectangle(image, pick[static_cast<int>(i)], color, 2, 8, 0);
		}

		imshow("cars", image);
		imwrite("..//result//" + names[j], image);
		waitKey(1);
	}

	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69

效果如下:
12
3

如果训练无误,但测试时没有结果。说明数据集不够,训练样本太少。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/278459
推荐阅读
相关标签
  

闽ICP备14008679号