基于opencv训练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.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

参数解释:
-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

参数解释:
-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;
}

效果如下:
12
3

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

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是使用OpenCV进行汽车识别模型训练的简单步骤: 1. 收集和准备数据 首先,需要收集一些汽车的图片数据,并将其分为训练集和测试集。确保数据集中包含不同角度、不同颜色和不同大小的车辆图片。 2. 安装OpenCV 在开始训练模型之前,需要安装OpenCV库。可以通过以下命令在Java项目中添加OpenCV依赖: ```xml <dependency> <groupId>org.openpnp</groupId> <artifactId>opencv</artifactId> <version>3.4.0-1</version> </dependency> ``` 3. 提取特征 使用OpenCVHaar特征分类器,可以提取车辆图片的特征。可以使用OpenCV自带的`opencv_createsamples`工具来创建正样本和负样本,然后使用`opencv_traincascade`工具来训练Haar分类器。 4. 训练模型 在提取特征后,可以使用OpenCV训练Haar分类器。训练过程可能需要一些时间,具体时间取决于数据集的大小和计算机的性能。训练完后,将生成一个XML文件,其中包含训练好的模型。 5. 测试模型 可以使用测试集测试训练好的模型。可以使用OpenCV的`CascadeClassifier`类来加载训练好的XML文件,并使用`detectMultiScale`方法来检测汽车。 ```java CascadeClassifier carDetector = new CascadeClassifier("path/to/trained/model.xml"); Mat image = Imgcodecs.imread("path/to/test/image.jpg"); MatOfRect cars = new MatOfRect(); carDetector.detectMultiScale(image, cars); ``` 以上是使用OpenCV训练汽车识别模型的大致步骤,具体实现细节可能因数据集和任务而异。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值