[关闭]
@dragonfive 2016-11-20T08:27:02.000000Z 字数 4618 阅读 1363

adaboost算法训练分类器

计算机视觉


摘要

视觉目标检测的机器学习法分三步:

  1. 一幅图像中,每个像素经过很少操作便可以到积分图。任何位置任何尺度的Haar特征都可以快速地被计算出来。
  2. 选择少量关键特征形成高效的分类器,筛选程序是一个简单修改的AdaBoost程序:约束弱学习,使每一个弱分类器返回时仅可依赖1个特征。每个改善过程的阶段,即选择一个新的弱分类器。
  3. 以级联的方式不断合并分类器,能够很快丢弃图像的背景区域。通过尽可能地迅速确定目标可能出现在哪些区域,并且只在这些有希望的区域进行更复杂的处理,检测器的速度得以大幅提高。实现该方法的关键是注意力过程中的“负误视”(在模式识别中,将属于物体标注为不属于物体)的概率。在几乎所有的情况下,目标实例必须由注意的过滤器选择(?)。

那些没有被最初的分类器排除的子窗口,会由接下来的一系列分类器再处理,每个分类器都比其前一个稍有复杂。如果某个子窗口被任一个分类器排除,那它将不会被进一步处理。该级联检测基本上可看做是一个退化型决策树。

特征

我们选择了特定的三类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的一种变种,既可以筛选出小规模特征集又可以训练分类器。

其算法本身是通过改变数据分布来实现的,它根据每次训练集之中每个样本的分类是否正确,以及上次的总体分类的准确率,来确定每个样本的权值。

  1. 使用加权后选取的训练数据代替随机选取的训练样本,这样将训练的焦点集中在比较难分的训练数据样本上;
  2. 将弱分类器联合起来,使用加权的投票机制代替平均投票机制。让分类效果好的弱分类器具有较大的权重,而分类效果差的分类器具有较小的权重。

OpenCV自带的adaboost程序能够根据用户输入的正样本集与负样本集训练分类器,常用于人脸检测,行人检测等。它的默认特征采用了Haar,不支持其它特征。

Adaboost的原理简述:

原文
这个名称是“adaptive boosting”的缩写,在AdaBoost方法中,每一个训练样本都被赋予一个权重,表明它被某个分类分类器选入训练集的概率。如果某个样本点已经被准确分类,那么在构造下一个训练集中,它被选中的概率就被降低;相反,如果某个样本点没有被正确分类,那么它的权重就得到提高。通过这样的方式,AdaBoost方法能够“聚焦于”那么较为困难(更富有信息)的样本上。在具体实现上,最初令每一个样本的权重都相同,对于第k次迭代操作,我们就根据这些权重来选取样本点。

简单来说,Adaboost是一种迭代算法,它的核心思想是在初始的权重数据分布下训练得到一个弱分类器(2类分类器),
每个Haar特征对应看一个弱分类器,但并不是任伺一个Haar特征都能较好的描述人脸灰度分布的某一特点,如何从大量的Haar特征中挑选出最优的Haar特征并制作成分类器用于人脸检测,这是AdaBoost算法训练过程所要解决的关键问题。

训练分类器的步骤

目标检测分为三个步骤:
1、 样本的创建
2、 训练分类器
3、 利用训练好的分类器进行目标检测。

流程

样本创建

训练样本分为正例样本和反例样本,其中正例样本是指待检目标样本,反例样本指其它任意图片,但这些图片不能包含目标特征。

负样本

负样本由背景描述文件来描述(每一行包含了一个负样本图片的文件名(基于描述文件的相对路径))。描述文件末尾貌似不能有空行。
该文件创建方法如下:具体方法是在Dos下的进入你的图片目录,输入

  1. dir /b > negdata.dat

把最后一行negdata.dat删除,就生成了负样本描述文件。

正样本

先生成文本描述文件
然后生成vec文件,本质上来讲,vec文件用来加速机器学习。

  1. 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

训练分类器

如何用opencv训练自己的分类器

opencv训练分类器的一些原理

  1. 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级分类器,几分钟就结束了,识别梁朝伟图像,发现同时识别到了其它部位,可能是样本数太少的缘故。
test2.jpg

用3000个正样本和2500个负样本训练20级分类器,训练半个小时后,训练到第7级的时候开始变慢。经常需要在黑框敲回车才能继续进行。最后程序卡死。

现在用3000个正样本和2500个负样本训练20级分类器,训练了7个小时了,依然停留在第8级的训练中,前6级很快就结束了,后面的分类器就越来越复杂,训练越来越慢。

用opencv自带的一些人脸检测分类器检测人脸,检测一般的图像没有问题。
result6.jpg

但是也会出现不能完全检测或者出现错误检测的情况。

下图是用opencv自带的haarcascade_frontalface_alt2.xml检测的邻家小孩的结果。旁边的小孩表情奇怪没有检测到,但是天上并没有表情不知道为什么划了个圈。
result2.jpg

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

result3.jpg

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

result4.jpg

result5.jpg

result6.jpg

状态

  1. 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
  1. 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

  1. 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. 为什么训练出来的xml文件不能检测人脸?一直卡在检测界面上。研究发现正样本里不仅有人脸,而且包括一些不含人脸的头发照。如果去掉这些照片就能正常检测。
  2. 卡在下面的这种界面
  1. *** 1 cluster ***
  2. POS: 1100 1131 0.972591
  3. __

这就说明负样本满载,用完了,需要新加一些负样本才可以继续。
3.

问题

  1. 船只样本怎么弄
  2. 为什么自己训练分类器这么慢

      
      
      
      
      
      
      
      
      
      
      
      未完
      

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注