从下述几篇文章中总结: - OpenCV中Adaboost训练的经验总结 - 采用opencv_cascadetrain进行训练的步骤及注意事项 - 使用opencv_traincascade训练遇到的问题总汇

在讲下面内容时首先应先清楚一件事情,自己收集到的原始负样本和参与训练的负样本(numNeg)不是同一个概念,两者无必然联系,通过在原始负样本图像上滑动和scale窗口得到一批预处理负样本图像,然后只有这些图像被前n-1级强分类器错判为正样本才算的上是参与第n级强分类器训练的负样本,这是一个缓慢的过程,这也是NEG count的填充过程。

  1. 收集到的原始负样本尺寸须知
  • 收集到的原始负样本图像最好拥有不同于正样本的尺寸,且要足够大,因为进入训练程序之后滑动窗口的大小就变成了正样本尺寸的大小,当原始负样本图像与正样本尺寸大小相同时,就无法在原始负样本图像上滑动来获得大量的训练用负样本,再加上如果收集到的原始负样本的数量可能并不比正样本多多少,也许就是3、4倍,这样的话,没训练几级强分类器训练程序就会退出,并提示Train dataset for temp stage can not be filled. Branch training terminated。但如果达到上百倍的时候,且能保持numPos和numNeg数量比最为1:3左右,这样也能达到不错的效果。
  1. numPos和numNeg数量比最好是1:3左右
  • 当numPos和numNeg比例接近的时候1:1,对numNeg内负样本的看中程度很低,在实际的生活中负样本肯定远远多于正样本。
  • 当numPos和numNeg比例较大的时候1:10,对numNeg内负样本多于看中而忽略了正样本的统计特性,造成正样本权重总和很小,当权重小于一定程度的时候可能很大一部分正样本都不参与训练了。
  • 原始负样本的数目不用很大,只要其尺寸足够大,内容足够多样,我们就可以设置一个和numPOS成1:3比例的numNeg,让训练程序自动地在原始负样本上通过滑动和scale窗口来获取numNeg个负样本。也就是说,numPos:numNeg = 1:3是最优的,寻找的原始负样本和numNeg之间没有必然的联系。
  • 采集一个很大原始负样本集,且尺寸相当大,内容相当丰富的时候,但保持numPos:numNeg = 1:3,这样就会避免样本不足引起的错误提示:Train dataset for temp stage can not be filled. Branch training terminated。注意:numPos:numNeg = 1:3时,训练程序照样会取遍整个原始负样本集,以确保能从其上取到numNeg个负样本。推荐做法!!!
  1. 正样本描述文件中需要指出目标在每个样本中的数量和位置
  • 例如:pos1.jpg 2 x1 y1 width1 height1 x2 y2 width2 height2
    这句描述表示在图片pos1上有2个目标,并列出了两个目标在图片中的位置
  • 特殊情况:若正样本为在原始图像上裁剪的目标部分,则图像可直接描述为:
    pos.jpg 1 0 0 width height
  1. 设置正确的-numPos参数
  • 实际准备的正样本数量(读入vec-file的正样本数) >= numPos + (numStage - 1) * numPos * (1 - minHitRate)
    这是numPos的最低标准,但因为实际的HR(HitRate)会比minHitRate高,所以在设置numPos时可以将其设置的稍微再大些,毕竟最终的目的是要尽量让所有的正样本都参与到训练中。但是,过大肯定是不对的,会出错,并提示以下信息:Bad argument < Can not get new positive sample. The most possible reason is insufficient count of samples in given vec-file.
  1. maxFalseAlarm(最大虚警率)的作用
  • FalseAlarm(虚警率)表示训练用的负样本中被错判为正样本的概率。
  • maxFalseAlarm直接影响着每个强分类器中弱分类器的个数。当maxFalseAlarm设置较大的时候,训练用的负样本中就会有很大一部分被错判为正样本(这些被错判的负样本图片会进入下一级参与训练),这样也就直接导致了一级强分类器中不会有太多的弱分类器;设置较小,每级强分类器中弱分类器的个数就较多,检测时间就会相对要长,在可以接受的检测时间下尽量降低maxFalseAlarm是我们要追求的目标。
  • 下一级参与训练的负样本为上一级被错判为正样本的负样本,而并非是重头开始将选择过的负样本也包含进来,只有当遍历完一遍原始负样本列表后才重头再扫描一遍。
  1. acceptanceRatio的含义,实际取出的负样本数与查询过的负样本数之比
  • 查询过的负样本是指,从原始负样本中通过滑动和scale获取的预处理负样本,实际取出的负样本为那些通过了前n-1级强分类器后仍被判为正样本的负样本。
  • 实际取出的负样本数一般都会达到设置的-numNeg。
  • 第n级时的acceptanceRatio = Stage0.FA*Stage1.FA* … *Stagen.FA
  • 当acceptanceRatio(n) 很低时,则表示经过n-1级强分类器仍能被错判为正样本的负样本的几率已经降到很小了,然而我们又必须要在每一级Stage处得到numNeg个负样本,这时就会不断地在原始图像上滑动和scale,直到攒够numNeg个才会开始第n级强分类器的训练。这也是为什么Stage的级数越高,NEG count的计数速度就越慢。
  • 当某一Stage(n)的FA为0时,则acceptanceRatio(n+1)必为0,也就表示在第n+1级Stage再也取不到一个负样本,此时就会终止训练,并提示:Train dataset for temp stage can not be filled. Branch training terminated.
  1. traincascade.exe命令行参数
  • 常用命令例子1: opencv_traincascade.exe -data dt -vec pos.vec -bg neg.txt -numPos 950 -numNeg 3555 -numStages 16 -precalcValbufSize 4048 -precalcdxBufSize 4048 -featureType LBP -w 50 -h 50 -numThreads 24
  • 常用命令例子2: opencv_traincascase.exe -data dt -vec pos.vec -bg neg.txt -numPos 950 -numNeg 3555 -w 50 -h 50
  • 例子中可能使用到的默认参数:
  • -numStages 默认值为20(Stage数不是越多越好,多了可能出现overfitting (过拟合)的情况)
  • -featureType 默认使用Haar特征,还有LBP和HOG可供选择(HOG为opencv2.4.0版本以上)
  • -numThreads 默认开启全部线程(OpenCV在编译时加入了TBB组件,否则不支持多线程)
  • -stageType 默认为BOOST类型
  • -bt 默认的boost分类器类型为GAB,还有DAB、RAB和LB可供选择
  • -mode 默认为BASIC模式(使用Haar特征的前提下,否则不使用此参数)
  • 其他详细参数请查看:链接内的第四部分
  1. Haar和LBP特征
  • 基于LBP特征的分类器几乎能和基于Harr特征的分类器拥有一样的性能,并且由于LBP属于整数型的特征,所以在训练的时候要比Haar特征快得多。
  1. createsamples程序的使用说明
  • createsamples有两个功能,一般使用它来创建vec文件,它的另一个功能会由一张正样本图片生成many artificial samples,通过旋转、缩放或者其他的transformations手段来实现吗,这对那些会在可预见的背景下出现的刚性图片非常有用(例如,网站上的logo),但如果你要寻找的object出现在很复杂的环境下(像人脸、行人,车辆的检测),那这样做就显得很无力。
  1. NEG count的填充过程解析
  1. 获取预处理负样本 —–> imgReader.getNeg(img)
    初始状态下,会先从原始负样本集中取出第一张图片,并将其缩放到一定比例,然后从这张缩放后图片上抠出一块窗口大小的图片作为第一张预处理负样本,之后会以stepFactor倍的步长在缩放图片上先左右后上下的滑动,再取出一系列的预处理负样本,直到取遍第一张缩放图。再然后,取出第二张原始负样本图,并将其按照一定的比例缩放,再在其上滑动取得预处理负样本,如此下去直到将原始负样本集取完一遍。取完一遍之后再次取出第一张原始负样本图,并将其缩放,但这次缩放的比例比第一遍的时候大,再按照上面方法滑动取预处理负样本。之后还会一遍一遍地从原始负样本集取图、增大缩放比例、滑动窗口。当把所有比例用完之后,即经历了winSize.width * winSize.height遍,会重新整个过程。
  2. 计算特征的积分图和标准差 —–> featureEvaluator->setImage( img, isPositive ? 1 : 0, i )
  3. 评估取出的预处理负样本 —–> predict( i )
    若取出的预处理负样本在经过前n-1级强分类器后仍被错判为正样本,则这个预处理负样本就可以成为训练下一级强分类器的训练负样本,如此循环直到取够numNeg个参与训练的负样本。又因为并非每个预处理负样本都能参与下一级强分类器的训练,所以就会存在一个比例acceptanceRatio,即参与下一级强分类器训练的负样本(numNeg)与取够numNeg个参与训练的负样本所需的预处理负样本(查询过的负样本数)之比。
  1. 内容已做了相当多的更新,修改了之前的错误!!!!