正式使用opencv里的训练和检测 - opencv_createsamples、opencv_traincascade

好久没有来写blog了,学生生涯终结,就不好好总结了,今天把opencv里关于adaboost训练和检测的过程记录下来,方便别人也方便自己~~~啊哈哈~~~~

一、基础知识准备

首先,opencv目前仅支持三种特征的训练检测, HAAR、LBP、HOG,选择哪个特征就去补充哪个吧。opencv的这个训练算法是基于adaboost而来的,所以需要先对adaboost进行基础知识补充啊,网上一大堆资料,同志们速度去查阅。我的资源里也有,大家去下载吧,这些我想都不是大家能直接拿来用的,我下面将直接手把手告诉大家训练怎么操作,以及要注意哪些细节。

二、关于正样本的准备

1、采集正样本图片

因为正样本最后需要大小归一化,所以我在采集样本的时候就直接把它从原图里抠出来了,方便后面缩放嘛,而不是只保存它的框个数和框位置信息(框个数、框位置信息看下一步解释),在裁剪的过程中尽量保持样本的长宽比例一致。比如我最后要归一化成20 X 20,在裁剪样本的时候,我都是20X20或者21X21、22X22等等,最大我也没有超过30X30(不超过跟我的自身用途有关,对于人脸检测这种要保证缩放不变性的样本,肯定就可以超过啦),我资源里也给出可以直接用的裁剪样本程序。

2、获取正样本路径列表

在你的图片文件夹里,编写一个bat程序(get route.bat,bat是避免每次都需要去dos框输入,那里又不能复制又不能粘贴!),如下所示:

运行bat文件,就会生成如下dat文件:

把这个dat文件中的所有非图片的路径都删掉,比如上图的头两行,再将bmp 替换成 bmp 1 0 0 20 20,如下:

(1代表个数,后四个分别对应 left top width height,如果我们之前不是把样本裁剪下来的,那么你的这个dat可能就长成这样1. bmp 3 1 3 24 24 26 28 25 25 60 80 26 26,1.bmp是完全的原图啊,你之前的样本就是从这张图上扣下来的)

3、获取供训练的vec文件

这里,我们得利用opencv里的一个程序叫opencv_createsamples.exe,可以把它拷贝出来。针对它的命令输入也是写成bat文件啦,因为cascade训练的时候用的是vec。如下:

运行bat,就在我们得pos文件夹里生成了如下vec文件:

就此有关正样本的东西准备结束。

三、关于负样本的准备

这个特别简单,直接拿原始图,不需要裁剪抠图(不裁剪还能保证样本的多样性),也不需要保存框(网上说只要保证比正样本大小大哈,大家就保证吧),只要把路径保存下来。同正样本类似,步骤图如下:

至此有关负样本的也准备完成。

四、开始训练吧

这里我们用opencv_traincascade.exe(opencv_haartraining.exe的用法跟这个很相似,具体需要输入哪些参数去看opencv的源码吧,网上资料也有很多,主要是opencv_traincascade.exe比opencv_haartraining.exe包含更多的特征,功能齐全些啊),直接上图:

命令输入也直接用bat文件,请务必保证好大小写一致,不然不予识别参数。小白兔,跑起来~~~

这是程序识别到的参数,没有错把,如果你哪个字母打错了,你就会发现这些参数会跟你预设的不一样啊,所以大家一定要看清楚了~~~~

跑啊跑啊跑啊跑,如下:

这一级的强训练器达到你预设的比例以后就跑去训练下一级了,同志们那个HR比例不要设置太高,不然会需要好多样本,然后stagenum不要设置太小啊,不然到时候拿去检测速度会很慢。

等这个bat跑结束,我的xml文件也生成了。如下:

其实这个训练可以中途停止的,因为下次开启时它会读取这些xml文件,接着进行上次未完成的训练。哈哈~~~~好人性化啊!

训练结束,我要到了我的cascade.xml文件,现在我要拿它去做检测了啊!呼呼~~~~

五、开始检测吧

opencv有个opencv_performance.exe程序用于检测,但是它只能用在用opencv_haartraining.exe来用的,所以我这里是针对一些列图片进行检测的,检测代码如下:

#include <windows.h>
#include <mmsystem.h>
#include <stdio.h>
#include <stdlib.h>
#include "wininet.h"
#include <direct.h>
#include <string.h>
#include <list>
#pragma comment(lib,"Wininet.lib")

#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/ml/ml.hpp"

#include <iostream>
#include <stdio.h>

using namespace std;
using namespace cv;

String cascadeName = "./cascade.xml";//训练数据

struct PathElem{
	TCHAR   SrcImgPath[MAX_PATH*2];
	TCHAR   RstImgPath[MAX_PATH*2];
};
int FindImgs(char * pSrcImgPath, char * pRstImgPath, std::list<PathElem> &ImgList);

int main( )
{
	CascadeClassifier cascade;//创建级联分类器对象
	std::list<PathElem> ImgList;
	std::list<PathElem>::iterator pImgListTemp;
	vector<Rect> rects;
	vector<Rect>::const_iterator pRect;

	double scale = 1.;
	Mat image;
	double t;
	if( !cascade.load( cascadeName ) )//从指定的文件目录中加载级联分类器
	{
		cerr << "ERROR: Could not load classifier cascade" << endl;
		return 0;
	}

	int nFlag = FindImgs("H:/SrcPic/","H:/RstPic/", ImgList);
	if(nFlag != 0)
	{
		cout<<"Read Image  error !  Input 0 to exit \n";
		exit(0);
	}

	pImgListTemp = ImgList.begin();
	for(int iik = 1; iik <= ImgList.size(); iik++,pImgListTemp++)
	{
		image = imread(pImgListTemp->SrcImgPath);
		if( !image.empty() )//读取图片数据不能为空
		{
			Mat gray, smallImg( cvRound (image.rows/scale), cvRound(image.cols/scale), CV_8UC1 );//将图片缩小,加快检测速度
			cvtColor( image, gray, CV_BGR2GRAY );//因为用的是类haar特征,所以都是基于灰度图像的,这里要转换成灰度图像
			resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR );//将尺寸缩小到1/scale,用线性插值
			equalizeHist( smallImg, smallImg );//直方图均衡

			//detectMultiScale函数中smallImg表示的是要检测的输入图像为smallImg,rects表示检测到的目标序列,1.1表示
			//每次图像尺寸减小的比例为1.1,2表示每一个目标至少要被检测到3次才算是真的目标(因为周围的像素和不同的窗口大
			//小都可以检测到目标),CV_HAAR_SCALE_IMAGE表示不是缩放分类器来检测,而是缩放图像,Size(30, 30)为目标的
			//最小最大尺寸
			rects.clear();
			printf( "begin...\n");
			t = (double)cvGetTickCount();//用来计算算法执行时间
			cascade.detectMultiScale(smallImg,rects,1.1,2,0,Size(20,20),Size(30,30));
			//|CV_HAAR_FIND_BIGGEST_OBJECT//|CV_HAAR_DO_ROUGH_SEARCH|CV_HAAR_SCALE_IMAGE,

			t = (double)cvGetTickCount() - t;
			printf( "detection time = %g ms\n\n", t/((double)cvGetTickFrequency()*1000.) );
			for(pRect = rects.begin(); pRect != rects.end(); pRect++)
			{
				rectangle(image,cvPoint(pRect->x,pRect->y),cvPoint(pRect->x+pRect->width,pRect->y+pRect->height),cvScalar(0,255,0));
			}
			imwrite(pImgListTemp->RstImgPath,image);
		}
	}

	return 0;
}

int FindImgs(char * pSrcImgPath, char * pRstImgPath, std::list<PathElem> &ImgList)
{
	//源图片存在的目录
	TCHAR   szFileT1[MAX_PATH*2];
	lstrcpy(szFileT1,TEXT(pSrcImgPath));
	lstrcat(szFileT1, TEXT("*.*"));

	//结果图片存放的目录
	TCHAR   RstAddr[MAX_PATH*2];
	lstrcpy(RstAddr,TEXT(pRstImgPath));
	_mkdir(RstAddr);   //创建文件夹

	WIN32_FIND_DATA   wfd;
	HANDLE   hFind   =   FindFirstFile(szFileT1, &wfd); 

	PathElem stPathElemTemp;
	if(hFind != INVALID_HANDLE_VALUE)
	{
		do
		{
			if(wfd.cFileName[0] == TEXT('.'))
				continue;
			if(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY || strcmp("Thumbs.db", TEXT(wfd.cFileName)) == 0)
			{
				;
			}
			else
			{ 

				TCHAR   SrcImgPath[MAX_PATH*2];
				lstrcpy(SrcImgPath, pSrcImgPath);
				lstrcat(SrcImgPath, TEXT(wfd.cFileName));

				lstrcpy(stPathElemTemp.SrcImgPath, SrcImgPath); 

				TCHAR   AdressTemp[MAX_PATH*2];
				lstrcpy(AdressTemp,pRstImgPath); 

				//lstrcat(AdressTemp, TEXT("/"));
				lstrcat(AdressTemp, TEXT(wfd.cFileName));
				lstrcpy(stPathElemTemp.RstImgPath, AdressTemp); 

				ImgList.push_back(stPathElemTemp);

			}
		}while(FindNextFile(hFind, &wfd));
	}
	else
	{
		return -1;
	}
	return 0;
}

自己看看自己的检测结果咯。效果不好的改进样本,调整训练参数吧~~~嘎嘎

我觉得我写的够白痴,很方便大家直接拿来用。其中一些细节,大家自己琢磨吧~88

时间: 2024-10-11 10:57:28

正式使用opencv里的训练和检测 - opencv_createsamples、opencv_traincascade的相关文章

Hu矩SVM训练及检测-----OpenCV

关键词:Hu矩,SVM,OpenCV 在图像中进行目标物识别,涉及到特定区域内是否存在目标物,SVM可在样本量较少情况下对正负样本(图片中前景背景)做出良好区分,图片基本特征包括诸如HOG.LBP.HAAR等,在具体进行物体检测时考虑结合待检测物特点利用或设计新特征进行训练并分类.本文以几何不变矩为例说明OpenCV中SVM分类器的一般使用过程,下面依次简述Hu矩函数.SVM参数设置及实例演示. 1.Hu求解 double M[7];//Hu矩输出 Moments mo; //矩变量 src=i

如何用OpenCV自带的adaboost程序训练并检测目标

http://www.cnblogs.com/easymind223/archive/2012/07/03/2574826.html OpenCV自带的adaboost程序能够根据用户输入的正样本集与负样本集训练分类器,常用于人脸检测,行人检测等.它的默认特征采用了Haar,不支持其它特征. Adaboost的原理简述:(原文) 每个Haar特征对应看一个弱分类器,但并不是任伺一个Haar特征都能较好的描述人脸灰度分布的某一特点,如何从大量的Haar特征中挑选出最优的Haar特征并制作成分类器用

如何使用opencv自带工具训练人脸检测分类器

前言 参考 1.opencv人脸检测训练分类器及其常见问题-译文-Good: 2.FAQ-opencv-haartraining-原文: 3.人脸检测训练心得: 4.opencv_traincascade支持Haar和LBP特征: 5.如何使用opencv自带工具训练分类器: 6.如何使用工具进行训练: 7.如何训练详解: 8.opencv中文论坛-级联分类器训练: 完 原文地址:https://www.cnblogs.com/happyamyhope/p/9706844.html

opencv学习笔记霍夫变换——直线检测

参考大佬博文:blog.csdn.net/jia20003/article/details/7724530 lps-683.iteye.com/blog/2254368 openCV里有两个函数(比较常用)处理霍夫变换直线检测,有什么区别呢. CvHoughLine:是用于标准的霍夫变换方法 CvHoughLine2:可以使用三种霍夫变换的方法,分别是标准霍夫变换(SHT).多尺度标准霍夫变换(MSHT).累计概率霍夫变换(PPHT). 函数原型: CvSeq* cvHoughLines2( C

opencv里vector的内存的申请和释放的问题

改成: CvMemStorage* m_storage=cvCreateMemStorage(0); CvSeq * m_contour=0; cvFindContours( &IPlImage(img), m_storage, &m_contour, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0)); //释放内存 cvReleaseMemStorage(&m_storage); msdn

基于OpenCV读取摄像头进行人脸检测和人脸识别

前段时间使用OpenCV的库函数实现了人脸检测和人脸识别,笔者的实验环境为VS2010+OpenCV2.4.4,opencv的环境配置网上有很多,不再赘述.检测的代码网上很多,记不清楚从哪儿copy的了,识别的代码是从OpenCV官网上找到的:http://docs.opencv.org/trunk/modules/contrib/doc/facerec/facerec_api.html 需要注意的是,opencv的FaceRecogizer目前有三个类实现了它,特征脸和fisherface方法

OpenCV实践之路——人脸检测(C++/Python) 【转】

转自:http://blog.csdn.net/xingchenbingbuyu/article/details/51105159 版权声明:本文为博主原创文章,转载请联系作者取得授权. 本文由@星沉阁冰不语出品,转载请注明作者和出处. 文章链接:http://blog.csdn.net/xingchenbingbuyu/article/details/51105159 微博:http://weibo.com/xingchenbing  之前一直觉得人脸检测是非常麻烦的,即使是用OpenCV,麻

OpenCV中Adaboost训练的经验总结

以OpenCV训练级联Adaboost为例进行说明 numPos: 12000 numNeg: 120000 numStages: 15 precalcValBufSize[Mb] : 1000 precalcIdxBufSize[Mb] : 800 stageType: BOOST featureType: HOG sampleWidth: 40 sampleHeight: 40 boostType: DAB minHitRate: 0.999 maxFalseAlarmRate: 0.7 w

OpenCV实践之路——人脸检测(C++/Python)

之前一直觉得人脸检测是非常麻烦的,即使是用opencv,麻烦到我都不敢去碰.这两天仔细看了下,如果只是调用opencv自带的分类器和函数的话,简直是简单.这不,正好最近也在学习Python,索性就用C++和Python两种语言都实现一下.当然,我现在这个是最简单的版本. 步骤: 调用opencv训练好的分类器和自带的检测函数检测人脸人眼等的步骤简单直接: 1.加载分类器,当然分类器事先要放在工程目录中去.分类器本来的位置是在*\opencv\sources\data\haarcascades(h