opencv人脸检测分类器训练小结

这两天在初学目标检测的算法及步骤,其中人脸检测作为最经典的算法,于是进行了重点研究。该算法最重要的是建立人脸检测分类器,因此我用了一天的时间来学习分类器的训练。这方面的资料很多,但是能按照一个资料运行出结果的确实没有找到,因此我总结了自己的训练经验。

  目标检测分为三个步骤:

  1、样本的创建

  2、训练分类器

  3、利用训练的分类器进行目标检测

第一步:样本的创建

 ◆     样本分两种: 正样本与负样本(也有人翻译成:正例样本和反例样本),其中正样本是指待检目标样本(例如人脸,汽车,鼻子等),负样本指其它任意图片。

 ◆     所有样本图片都应该有同一尺寸,如32 * 32,并放在相应文件目录下,

 ◆     集合文件格式(collection file format)和描述文件格式(description file format) 

集合文件格式(collection file format)就是如下形的描述文件:

[filename]

[filename]

[filename]

  …

 描述文件格式(description file format)就是如下形的描述文件:

[filename] [# of objects] [[x y width height] [... 2nd object] ...]

[filename] [# of objects] [[x y width height] [... 2nd object] ...]

[filename] [# of objects] [[x y width height] [... 2nd object] ...]

…. 

(x, y) 指左上角的坐标,width和 height 分别是样本的宽和高,这里我的图片是32*32的,所以两个值都是32

!!!!!!!负样本用集合文件格式描述,正样本用描述文件格式描述。  

一、把所有正样本图片放在posdata的文件夹下,把所有负样本图片放在negdata文件夹下 

(这里我以人脸图片样本为例)

   

  

(注:以上这些32*32 的图片均来自MIT人脸库,可以在csdn下载) 

二. 分别为正样本和负样本创建描述文件 

A.  为正样本创建描述文件格式文件info.txt,并且把这个文件放在与样本图片同一目录下,例如我的目录为C:/OpenCV2.1/bin/posdata

a)      在命令行下 输入以下命令: dir /b > info.txt

 

b)      打开info.txt, 选择编辑-》替换,把所有的bmp 换成 bmp 1 0 0 32 32

c)      删除info.txt最后一行的 “info.txt”

 B.  为负样本创建集合文件格式文件bg.txt, 并且把这个文件放在与样本图片同一目录下,例如我的目录为I:/negdata

a)      在命令行下 输入以下命令: dir /b > bg.txt

b)      删除bg.txt最后一行的 “bg.txt”

三、创建样本

许多文章都说Opencv 自带有创建样本的exe 文件,但是我的目录下却没有,所以我只能自己生成createsamples.exe文件,首先在opencv解压文件夹里找到opencv->apps->haartraining中createsample.cpp文件,然后将该文件使用的所有.h和.cpp文件都加入到一个工程中,然后编译运行,在编译过程中会有各种错误,可根据错误提示进行相应的改正,其中最主要的是缺少"#include "stdafx.h“",其他的错误就是包含的文件添加不够导致的。 这里我创建10个sample:

将检测的正负样本文件和createsamples.exe文件放到同一根目录下,并在DOS命令下输入以下内容:

命令是: createsamples.exe -info info.txt -vec pos.vec -num 10 -w 20 -h 20 

(关于 opencv_createsamples.exe 的参数用法,在参考英文资料网址http://note.sonots.com/SciSoftware/haartraining.html#e134e74e,里有详细介绍; 

需要说明的是,我这里用的参数并没有 –bg, 因为根据那份文档,有了 –vec 和 –info 之后,就表示:Create training samples from some (从很多正样本中创建sample, 没有distortions) 

四、训练分类器

如果在opencv的解压文件夹里没有找到haartraining.exe文件,则需要自己生成,其生成步骤与前一步createsamples.exe的生成步骤相同。

首先在根目录下建xml文件夹存放训练的分类器,并输入命令:

haartraining.exe -data xml-vec pos.vec -bg negdata0.txt -npos 10 -nneg 10  -mem 512 -model  all -w 20 -h 20

这时会在根目录下的xml文件夹里生成许多.txt文件。

五、将生成的.txt文件制作成.xml文件

  首先在opencv解压文件夹里找到opencv->samples->c->convert_cascade.c,将其加入到工程中,编译运行生成convert_cascade.exe文件,并将其放到原来的根目录下,在DOS命令下输入:

convert_cascade --size = "32x32" xml haarcascade.xml

则在根目录下生成该.xml文件。

五、利用生成的.xml分类器进行人脸检测

 该代码如下,将lena.jpg放到工程文件夹下,由于本.xml只训练了10张照片,样本数少,所以检测效果很差,但是检测过程是正确且完整的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include "stdafx.h"
#include "cv.h"
#include "highgui.h"
  
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include <float.h>
#include <limits.h>
#include <time.h>
#include <ctype.h>
  
#ifdef _EiC
#define WIN32
#endif
  IplImage* image;
  IplImage* copyimage;
static  CvMemStorage* storage = 0;
static  CvHaarClassifierCascade* cascade = 0;
  
void  detect_and_draw( IplImage* image );
  
const  char * cascade_name =  "xml.xml" ;
  
int  main(  int  argc,  char ** argv )
{   
    cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );
  
     if ( !cascade )
     {
         fprintf ( stderr,  "ERROR: Could not load classifier cascade\n"  );
         fprintf ( stderr,
         "Usage: facedetect --cascade=\"<cascade_path>\" [filename|camera_index]\n"  );
         return  -1;
     }
     storage = cvCreateMemStorage(0);
  
     image = cvLoadImage( "lena.jpg" );
     if ( !image ) return  -1;
 
     cvNamedWindow( "Original Image" ,1);
     cvShowImage( "Original Image" ,image);
 
     detect_and_draw( image );  
     
     cvWaitKey(0);
     cvDestroyWindow( "Original 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 );
     IplImage* small_img = cvCreateImage( cvSize( cvRound (img->width/scale),
                          cvRound (img->height/scale)),
                      8, 1 );
     int  i;
  
     cvCvtColor( img, gray, CV_BGR2GRAY );
     cvResize( gray, small_img, CV_INTER_LINEAR );
     cvEqualizeHist( small_img, small_img );
     cvClearMemStorage( storage );
  
     if ( cascade )
     {
         double  t = ( double )cvGetTickCount();
         CvSeq* faces = cvHaarDetectObjects( small_img, cascade, storage,
                                             1.1, 2, 0 /*CV_HAAR_DO_CANNY_PRUNING*/ ,
                                             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 );
             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 );
         }
     }
  
     cvShowImage(  "result" , img );
     cvReleaseImage( &gray );
     cvReleaseImage( &small_img );
}
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值