1. 创建xml文件
创建xml文件需要两个命令,在新版的opencv,命令名字为:opencv_createsamples和opencv_haartraining
(1)创建样本
命令格式:
opencv_createsamples.exe -vec pic.vec -info zheng\zhenglist.txt -bg fu\fulist.txt -num 20 -w 100 -h 20
-vec 生成样本的名字,-info 正样本的图片列表,-bg 负样本的图片列表, -num 正样本的名字, -w 和 -h 正样本需要统一的高度和宽度。
zhenglist.txt正样本的文件的格式:
cv_1.jpg 1 0 0 100 20
图片的名字,1代表一个样本, 图片的有效范围为从(0,0)开始到(100,20)结束,所以,在之前就必须把图片转换成100*20的,而且还是8位的,不能使彩色的。
所以为了方便,我也提供的一个命令去转换图片。
picoperate.exe放在样本的所在目录下,直接执行,PicList.txt是需要处理的图片列表,必须为这个名字,处理完成后的图片名字会在原来名字之前添加一个“cv_”字符串,如原来为1.jpg转换后变为cv_1.jpg。
需要注意的是,负样本对大小没有要求,最好也是8位的,灰色图片。
picoperate.zip
(2)训练样本
命令格式 :
opencv_haartraining.exe -data car -vec pic.vec -bg fu\fulist.txt -w 100 -h 20 -mem 800 -mode all -npos 20 -nneg 20
-data 输出名字,如果名字为car,最后结果为car.xml, -vec 样本的名字,就是上一步使用命令opencv_createsamples创建的文件,
-bg 负样本的文件列表,-w和-h也是正样本的大小。
-npos 是正样本的个数,-nneg 是负样本的个数。
如果样本很多的话这一步需要很多时间。
2. 样本的使用
1.load xml 文件
static CvHaarClassifierCascade *cascade = 0;
cascade = (CvHaarClassifierCascade*)cvLoad(cascade_name, 0, 0, 0 );
if( !cascade )
{
printf("load car.xml fail.\n");
return -1;
}
2. 开始检查
CvSeq* faces = cvHaarDetectObjects( img, cascade, storage,
1.1, 2, 0
//|CV_HAAR_FIND_BIGGEST_OBJECT
//|CV_HAAR_DO_ROUGH_SEARCH
|CV_HAAR_DO_CANNY_PRUNING
//|CV_HAAR_SCALE_IMAGE
,
cvSize(30, 30) );
3. 一个实例
#include "stdafx.h"
#include "cv.h"
#include "highgui.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
static CvMemStorage* storage = 0;
static CvHaarClassifierCascade *cascade = 0;
int use_nested_cascade = 0;
void detect_and_draw( IplImage* image );
const char* cascade_name = "car.xml";
double scale = 1;
int resizepic(IplImage *src, IplImage **img)
{
int time;
int widthabout = 300;
time = src->width / widthabout;
printf("width=%d,height=%d.\n", src->width, src->height);
if(time == 0)
{
if(src->width < (widthabout>>2))
{
time = widthabout / src->width;
*img = cvCreateImage(cvSize(src->width*time, src->height*time), src->depth, src->nChannels);
}
else
{
*img = cvCreateImage(cvSize(src->width, src->height), src->depth, src->nChannels);
cvCopy(src, *img);
goto RESIZEEND;
}
}
else
{
*img = cvCreateImage(cvSize(src->width/time, src->height/time), src->depth, src->nChannels);
}
cvResize(src, *img, CV_INTER_LINEAR);
//IplImage *pyr = cvCreateImage(cvSize(src->width/2/time, src->height/2/time), src->depth, src->nChannels);
//cvPyrDown(*img, pyr, 7);
//cvPyrUp(pyr, *img, 7);
RESIZEEND:
//cvNamedWindow("ResizeSource");
//cvShowImage("ResizeSource", *img );
//cvMoveWindow("ResizeSource", 20, 100);
return 0;
}
int findcar(char *filename )
{
CvCapture* capture = 0;
IplImage *image, *src;
storage = cvCreateMemStorage(0);
cascade = (CvHaarClassifierCascade*)cvLoad(cascade_name, 0, 0, 0 );
if( !cascade )
{
printf("load car.xml fail.\n");
return -1;
}
image = cvLoadImage( filename, 0 );
resizepic(image, &src);
cvNamedWindow( "source", 1 );
//cvShowImage("source", src);
detect_and_draw(src);
cvDestroyWindow("source");
return 0;
}
void detect_and_draw( IplImage* img )
{
static CvScalar colors[] =
{
{{0,0,255}},
{{0,128,255}},
{{0,255,255}},
{{0,255,0}},
{{255,128,0}},
{{255,255,0}},
{{255,0,0}},
{{255,0,255}}
};
int i, j;
cvEqualizeHist(img, img);
//cvClearMemStorage( storage );
if(cascade)
{
double t = (double)cvGetTickCount();
CvSeq* faces = cvHaarDetectObjects( img, cascade, storage,
1.1, 2, 0
//|CV_HAAR_FIND_BIGGEST_OBJECT
//|CV_HAAR_DO_ROUGH_SEARCH
|CV_HAAR_DO_CANNY_PRUNING
//|CV_HAAR_SCALE_IMAGE
,
cvSize(30, 30) );
t = (double)cvGetTickCount() - t;
printf( "detection time = %gms\n", t/((double)cvGetTickFrequency()*1000.) );
for( i = 0; i < (faces ? faces->total : 0); i++ )
{
CvRect* r = (CvRect*)cvGetSeqElem( faces, i );
printf("rect is (%d,%d,%d,%d)\n", r->x, r->y, r->width, r->height);
cvRectangle (
img,
cvPoint(r->x,r->y),
cvPoint(r->x+r->width,r->y+r->height),
cvScalar(0x0,0x00,0x00) /* red */
);
}
}
cvShowImage( "source", img );
cvWaitKey(0);
}
char *strip(char *str)
{
char *cp = str ;
char *p = str ;
int len = strlen(str);
int i;
if (cp == NULL || *cp == '\0')
{
return NULL;
}
cp = cp + len;
while(cp > str)
{
cp--;
if ((*cp == ' ') || (*cp == '\t') || (*cp == '\n'))
*cp = '\0';
else
break;
}
for (cp = str; (*cp == ' ') || (*cp == '\t') || (*cp == '\n'); cp++);
len = strlen(cp);
for(i=0;i {
*p = *cp;
p++;
cp++;
}
*p='\0';
return str;
}
int _tmain(int argc, _TCHAR* argv[])
{
FILE* fp = fopen( "PicList.txt", "r" );
char picname[256] = {0};
int ret;
if(!fp)
{
printf("Can not open PicList.txt.\n");
return -1;
}
while (!feof(fp))
{
memset(picname, 0, sizeof(picname));
fgets(picname, 128, fp);
strip(picname);
if (picname[0] == '#' || strlen(picname) <= 1)
continue;
printf("picName is %s.\n", picname);
ret = findcar(picname);
if(ret<0)
{
break;
}
}
fclose(fp);
return 0;
}