一、准备正负样本
1、 最好大小均一致,本次用的是35*35
2、 准备数量:正负样本均达200以上,正样本数量是负样本的两倍左右。建议:正样本—1500,负样本—3000,当然越多越好
3、 样本不能重复,防止出现过拟合,定位效果不佳
二、批量修改图片名称
首先需要对图片名称进行批量处理,建议使用Total_Commander,这里给一个破解版的下载链接:http://download.csdn.net/download/sinat_30071459/9582586
使用很方便,打开TOTALCMD64.EXE,然后选择需要批量处理名的所有图片,建议选择000001.jpg、000002.jpg..格式,只需要在TOTALCMD64.EXE中名称格式选择N,字符宽选择6即可
三、生成txt文件
我这里写了两个简单的python脚本,亲测可行(NOTE:如果你在windows下训练就在windows下执行该脚本生成txt,该txt不能被linux用,会出现内存错误。在linux下训练只需在linux下执行该脚本生成txt即可)
还需要注意一点:txt中图片名称都是相对路径,即我当前目录中要有所有的txt和neg图片文件夹与pos图片文件夹
#pos.txt
boot_path='/home/ubuntu/workspace/build-information-list/'
name='pos'
full_path=boot_path+name+'.txt'
with open(full_path,'w') as file:
for i in range(1,1501):
s=str(i)
ss=s.zfill(6)
file.write('pos/'+ss+'.jpg'+' '+'1'+' '+'0'+' '+'0'+' '+'35'+' '+'35')
file.write('\n')
file.close()
print "Done"
#neg.txt
boot_path='/home/ubuntu/workspace/build-information-list/'
name='neg'
full_path=boot_path+name+'.txt'
with open(full_path,'w') as file:
for i in range(1,3001):
s=str(i)
ss=s.zfill(6)
file.write('neg/'+ss+'.jpg')
file.write('\n')
file.close()
print "Done"
四、生成vec
NOTE:opencv文件在我当前目录的前前文件夹
只需执行
./../../opencv2.4.9/build/bin/opencv_createsamples -vec pos.vec -info pos.txt -num 1500 -w 35 -h 35
就会在当前文件夹下生成名为pos.vec
五、训练
./../../opencv2.4.9/build/bin/opencv_haartraining -data xml -vec pos.vec -bg neg.txt -nstages 7 -npos 750 -nneg 1500 -mem 1280 -mode all -w 24 -h 24
data为生成xml文件夹,bg为副样本txt,-nstages 7为训练层数为7,训练时间会随着训练层数的数目呈指数增长。mem为分配内存,单位MB,-mode all 表示使用haar特征集的种类既有垂直的,又有45度角旋转的。
可在当前文件夹下生成xml文件夹
六、测试
//#include "iostream.h"
//#include "stdafx.h"
#include "highgui.h"
#include "cv.h"
#include <stdio.h>
static CvHaarClassifierCascade* cascade=0;
static CvMemStorage* storage=0;
void detect_and_draw(IplImage* img);
const char* cascade_name="tiaotong.xml"; //此xml文件是刚才你产生的,拷贝到项目文件中,把名字改了
int main(int argc,char* argv[])
{
cascade=(CvHaarClassifierCascade*)cvLoad(cascade_name,0,0,0);
if (!cascade)
{
fprintf(stderr,"ERROR!\n");
return -1;
}
printf("fwfwefwe\n");
storage=cvCreateMemStorage(0);
const char* filename="000062.jpg"; //你要测试的图片名字
IplImage* image=cvLoadImage(filename,1);
printf("fwfwefwe\n");
if (!image)
{
fprintf(stderr,"Load image error!\n");
return -1;
}
cvNamedWindow("result",1);
printf("fwfwefwe\n");
detect_and_draw(image);
printf("fwfwefwe\n");
cvWaitKey();
printf("fwfwefwe\n");
cvReleaseImage(&image);
cvDestroyWindow("result");
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}}
};
double scale=1.3;
IplImage* gray=cvCreateImage(cvSize(img->width,img->height),8,1);
printf("fwfwefwe\n");
IplImage* small_img=cvCreateImage(cvSize(cvRound(img->width/scale),cvRound(img->height/scale)),8,1);
printf("fwfwefwe\n");
cvCvtColor(img,gray,CV_BGR2GRAY);
cvResize(gray,small_img,CV_INTER_LINEAR);
cvEqualizeHist(small_img,small_img);
printf("fwfwefwe\n");
cvClearMemStorage(storage);
printf("fwfwefwe\n");
if (cascade)
{
CvSeq* faces=cvHaarDetectObjects(small_img,cascade,storage,1.1,2,0,cvSize(30,30));
printf("fwfwefwe\n");
for (int i=0;i<(faces ? faces->total:0);i++)
{
CvRect* r=(CvRect*)cvGetSeqElem(faces,i);
CvPoint center;
int radius;
center.x=cvRound((r->x+r->width*0.5)*scale);
center.y=cvRound((r->y+r->height*0.5)*scale);
radius=cvRound((r->width+r->height)*0.25*scale);
cvCircle(img,center,radius,colors[i%8],3,8,0);
printf("fwfwefwe\n");
}
}
printf("fwfwefwe\n");
cvShowImage("Result",img);
printf("fwfwefwe\n");
cvReleaseImage(&gray);
printf("fwfwefwe\n");
cvReleaseImage(&small_img);
}
七、结果
由于我只训练了4层,图片质量也不好,所以效果很垃圾 –。–
八、参考
http://blog.csdn.net/liulina603/article/details/8184451
http://blog.sina.com.cn/s/blog_843485230101hjs7.html
http://blog.csdn.net/carson2005/article/details/8171571
http://blog.csdn.net/kxc0720/article/details/49252719
http://blog.csdn.net/itismelzp/article/details/50378468