利用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对训练样本要求很严格,样本处理较为困难,目前没有找到太好方法。