利用opencv的haartraining训练分类器分为三个步骤:
1.准备正负样本(正负样本的比例最好是1:3左右,这里用45个正样本,99个负样本,正样本要求统一背景包含各种不同的目标识别对象,且同一大小,也不能过大,这里用的是45*40大小的;负样本可以任意大小,但也不要过大,不能不含目标识别对象,最好用灰度图)
2.创建样本
3.训练分类器
具体方法如下:
找到opencv所在目录,bin目录下有两个.exe文件(opencv_createsamples.exe和opencv_haartraining.exe),注意较新的opencv版本的目录中没有bin文件夹,也没有这两个可执行文件,建议使用2.2或2.2之前版本。新版本中有相关的头文件,但具体使用方法还不了解。
将正负样本分别放在两个文件夹中,例如将两个文件夹命名为posdata和negdata,并为正负样本建立描述文件。在控制台窗口(win+R后输入cmd打开控制台窗口),进入到正样本文件夹下,输入dir /b > info.txt(info.txt就是正样本的描述文件)。
修改info.txt文件,打开info.txt后删除其中的info.txt,并且将所有bmp替换成bmp 1 0 0 45 40(45,40分别为宽和高)
进入到负样本文件夹下,输入dir /b > bg.txt(bg.txt就是负样本的描述文件)。修改bg.txt文件,打开bg.txt后删除其中的bg.txt。
控制台窗口进入到bin目录,输入opencv_createsamples.exe -info E:/vsProjects/FaceDetection/posdata/info.txt -vec a.vec -num 20 -w 45 -h 40建立20组样本。然后输入opencv_haartraining.exe -data data -vec D:/OpenCV2.2/bin/a.vec -bg E:/vsProjects/FaceDetection/negdata/bg.txt -npos 45 -nneg 99 -nstages 4 -nsplits 2 -mem 512 -nonsym -w 45 -h 40。这样就在bin训练生成了data.xml文件,下面就用这个文件检测目标物体。代码如下:
#include "stdafx.h"
#include <opencv2/opencv.hpp>
#include <cstdio>
#include <cstdlib>
#include <Windows.h>
#pragma comment(lib, "opencv_objdetect244d.lib")
using namespace std;
int main()
{
// 加载Haar特征检测分类器
// 训练的分类器
const char *pstrCascadeFileName = "D:\\opencv\\data\\haarcascades\\data.xml";
CvHaarClassifierCascade *pHaarCascade = NULL;
pHaarCascade = (CvHaarClassifierCascade*)cvLoad(pstrCascadeFileName);
// 载入图像
const char *pstrImageName = "../cup_test.jpg";
IplImage *pSrcImage = cvLoadImage(pstrImageName, CV_LOAD_IMAGE_UNCHANGED);
IplImage *pGrayImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 1);
cvCvtColor(pSrcImage, pGrayImage, CV_BGR2GRAY);
// 识别与标记
if (pHaarCascade != NULL)
{
CvScalar FaceCirclecolors[] =
{
{{0, 0, 255}},
{{0, 128, 255}},
{{0, 255, 255}},
{{0, 255, 0}},
{{255, 128, 0}},
{{255, 255, 0}},
{{255, 0, 0}},
{{255, 0, 255}}
};
CvMemStorage *pcvMStorage = cvCreateMemStorage(0);
cvClearMemStorage(pcvMStorage);
// 识别
DWORD dwTimeBegin, dwTimeEnd;
dwTimeBegin = GetTickCount();
CvSeq *pcvSeqFaces = cvHaarDetectObjects(pGrayImage, pHaarCascade, pcvMStorage);
dwTimeEnd = GetTickCount();
printf("目标物体个数: %d 识别用时: %d ms\n", pcvSeqFaces->total, dwTimeEnd - dwTimeBegin);
// 标记
for(int i = 0; i <pcvSeqFaces->total; i++)
{
CvRect* r = (CvRect*)cvGetSeqElem(pcvSeqFaces, i);
CvPoint center;
int radius;
center.x = cvRound((r->x + r->width * 0.5));
center.y = cvRound((r->y + r->height * 0.5));
radius = cvRound((r->width + r->height) * 0.25);
cvCircle(pSrcImage, center, radius, FaceCirclecolors[i % 8], 2);
}
cvReleaseMemStorage(&pcvMStorage);
}
const char *pstrWindowsTitle = "物体识别";
cvNamedWindow(pstrWindowsTitle, CV_WINDOW_AUTOSIZE);
cvShowImage(pstrWindowsTitle, pSrcImage);
cvWaitKey(0);
cvDestroyWindow(pstrWindowsTitle);
cvReleaseImage(&pSrcImage);
cvReleaseImage(&pGrayImage);
return 0;
}
存在的问题:haartraining对训练样本要求很严格,样本处理较为困难,目前没有找到太好方法。