@dragonfive
2016-11-20T08:27:02.000000Z
字数 4618
阅读 1363
计算机视觉
视觉目标检测的机器学习法分三步:
那些没有被最初的分类器排除的子窗口,会由接下来的一系列分类器再处理,每个分类器都比其前一个稍有复杂。如果某个子窗口被任一个分类器排除,那它将不会被进一步处理。该级联检测基本上可看做是一个退化型决策树。
我们选择了特定的三类Haar特征(?):含2个矩形的特征、含3个矩形的特征、含4个矩形的特征。如下图:
矩形特征可以反映检测窗口之间的练习。白色矩形中的像素和减去黑色矩形中的像素和得到特征值。
积分图可以快速计算矩形特征。积分图像(x,y)处的值为原图(x,y)上边和左边所有像素的和,即:
根据上面的理论基础我们可以得到,使用积分图像可以把任意一个矩形用四个数组计算,这样我们能加快运算。
矩形D内的像素和可以按四个数组计算。位置1的积分图像的值就是矩阵A中的像素之和,位置2的值是A+B,位置3的值是A+C,位置4的知识A+B+C+D。那么D中的像素就是A+B+C+D-(A+B)-(A+C)+A,也就是4-2-3+1。
使用的是AdaBoost的一种变种,既可以筛选出小规模特征集又可以训练分类器。
其算法本身是通过改变数据分布来实现的,它根据每次训练集之中每个样本的分类是否正确,以及上次的总体分类的准确率,来确定每个样本的权值。
OpenCV自带的adaboost程序能够根据用户输入的正样本集与负样本集训练分类器,常用于人脸检测,行人检测等。它的默认特征采用了Haar,不支持其它特征。
原文
这个名称是“adaptive boosting”的缩写,在AdaBoost方法中,每一个训练样本都被赋予一个权重,表明它被某个分类分类器选入训练集的概率。如果某个样本点已经被准确分类,那么在构造下一个训练集中,它被选中的概率就被降低;相反,如果某个样本点没有被正确分类,那么它的权重就得到提高。通过这样的方式,AdaBoost方法能够“聚焦于”那么较为困难(更富有信息)的样本上。在具体实现上,最初令每一个样本的权重都相同,对于第k次迭代操作,我们就根据这些权重来选取样本点。
简单来说,Adaboost是一种迭代算法,它的核心思想是在初始的权重数据分布下训练得到一个弱分类器(2类分类器),
每个Haar特征对应看一个弱分类器,但并不是任伺一个Haar特征都能较好的描述人脸灰度分布的某一特点,如何从大量的Haar特征中挑选出最优的Haar特征并制作成分类器用于人脸检测,这是AdaBoost算法训练过程所要解决的关键问题。
目标检测分为三个步骤:
1、 样本的创建
2、 训练分类器
3、 利用训练好的分类器进行目标检测。

训练样本分为正例样本和反例样本,其中正例样本是指待检目标样本,反例样本指其它任意图片,但这些图片不能包含目标特征。
负样本由背景描述文件来描述(每一行包含了一个负样本图片的文件名(基于描述文件的相对路径))。描述文件末尾貌似不能有空行。
该文件创建方法如下:具体方法是在Dos下的进入你的图片目录,输入
dir /b > negdata.dat
把最后一行negdata.dat删除,就生成了负样本描述文件。
先生成文本描述文件
然后生成vec文件,本质上来讲,vec文件用来加速机器学习。
C:\Users\dragonfive\Desktop\manFace>"D:\Program Files\opencv_lib\opencv\build\x86\vc12\bin\opencv_createsamples.exe" -info "positice\posdata.dat" -vec data\pos.vec -num 60 -w 20 -h 20
C:\Users\dragonfive\Desktop\manFace>"D:\Program Files\opencv_lib\opencv\build\x86\vc12\bin\opencv_haartraining.exe" -data data\cascade -vec data\pos.vec -bg negative\negdata.dat -npos 60 -nneg 60 -mem 200 -mode ALL -w 20 -h 20
vec-file has to contain >= (numPos + (numStages-1) * (1 - minHitRate) * numPos) + S
7000 >= (numPos + (20-1) * (1 - 0.999) * numPos) + 2973
(7000 - 2973)/(1 + 19*0.001) >= numPos
numPos <= 4027/1.019
numPos <= 3951 ~~ 3950
and used:
-npos 3950 -nneg 2973
常见问题
-minhitrate 每一层的最低正确检测率,通常设为99.9%,如果有1000个正样本,你希望检测系统能检测出其中的999个。
-maxfalsealarm 0.5 最大错误接受率50%,如果有1000个负样本,允许检测系统错误的将其中500当作了检测目标。
首先,系统根据期望的hitrate创建分类器,然后计算分类器的falsealarm。如果falsealarm比设置的maxfalsealarm高,系统会拒绝这个分类器,开始创建新的分类器。
-nstages
通常级联分类器应该被设定14-25层就足够了,如果层数过多,分类器的false alarm就更小,但是产生级联分类器的时间更长,分类器的hitrate就更小,检测速度更慢。
-nsplits 树节点数的最小值。
-nsplits
简单介绍nsplits>=2的情况
决定用于阶段分类器的弱分类器。如果1,则一个简单的stump classifier被使用。如果是2或者更多,则带有number_of_splits个内部节点的CART分类器被使用。
-minpos 训练过程中,节点可使用的正样本数目。通常来说,minpos不小于npos / nsplits 。
训练分类器的过程中,会生成一些 txt文件,我们可以使用convert_cascade 工具生成xml文件。convert_cascade -size="20*20" haarcascade haarcascde.xml
使用performance工具来测试,其中正样本是训练过程中未使用的图片。
也可以使用opencv库函数里面的cvHaarDetectObjects函数进行人脸的检测。
针对一个只含一个脸的图像。
| 级数 | 100个识别出的人脸数 | 800个正样本识别的人脸数 |
|---|---|---|
| 4 | 35 | |
| 5 | 30 | |
| 6 | 30 | |
| 7 | 23 | |
| 8 | 17 | 6 |
| 9 | 17 | |
| 10 | 5 | |
| 11 | 4 | |
| 12 | 3 | |
| 13 | 3 | |
| 14 | 2 |
用46个正样本和66个负样本训练的3级分类器,几分钟就结束了,识别梁朝伟图像,发现同时识别到了其它部位,可能是样本数太少的缘故。

用3000个正样本和2500个负样本训练20级分类器,训练半个小时后,训练到第7级的时候开始变慢。经常需要在黑框敲回车才能继续进行。最后程序卡死。
现在用3000个正样本和2500个负样本训练20级分类器,训练了7个小时了,依然停留在第8级的训练中,前6级很快就结束了,后面的分类器就越来越复杂,训练越来越慢。
用opencv自带的一些人脸检测分类器检测人脸,检测一般的图像没有问题。

但是也会出现不能完全检测或者出现错误检测的情况。
下图是用opencv自带的haarcascade_frontalface_alt2.xml检测的邻家小孩的结果。旁边的小孩表情奇怪没有检测到,但是天上并没有表情不知道为什么划了个圈。

下图是用opencv自带的haarcascade_frontalface_alt.xml检测的邻家小孩的结果。圈在了另一个地方。

同样的一些人脸常常因为角度问题或遮挡问题没有检测到



C:\Users\dragonfive\Desktop\manFace>opencv_haartraining.exe -data "C:\\Users\\dragonfive\\Desktop\\100face\\data\\xlm6" -vec data/pos3.vec -npos 710 -bg "C:\\Users\\dragonfive\\Desktop\\face\\negdata\\neg.txt" -nneg 10926 -mem 1024 -nstages 10 -w 24 -h 24
C:\Users\dragonfive\Desktop\100face>opencv_haartraining.exe -data data/xlm4 -vec data/pos.vec -bg "C:\\Users\\dragonfive\\Desktop\\pos_neg\\neg_image\\neg.txt"-npos 89 -nneg 2500 -w 20 -h 20 -mem 1024 -nstages 18
2015年7月18日 09:32:25
C:\Users\dragonfive\Desktop\100face>opencv_haartraining.exe -data data/xlm5 -vec data/pos1.vec -bg "C:\\Users\\dragonfive\\Desktop\\face\\negdata\\neg.txt" -npos 200 -nneg 10926 -w 20 -h 20 -mem 2048 -nstages 18
*** 1 cluster ***POS: 1100 1131 0.972591__
这就说明负样本满载,用完了,需要新加一些负样本才可以继续。
3.
为什么自己训练分类器这么慢
未完