目标检测之训练opencv自带的分类器(opencv_haartraining 或 opencv_traincascade)

2022-05-09 14:08:22 浏览数 (1)

    最权威的说明,参考官方使用手册:

    http://www.OpenCV.org.cn/opencvdoc/2.3.2/html/doc/user_guide/ug_traincascade.html

    自带的分类器是adaboost分类器算法思想是通过迭代训练弱分类器得到一个强分类器。每次迭代得到局部最优的分类器,然后将局部最优的分类器权值相加最后得到一个可用的强分类器。

算法伪代码如下:

(1)初始化训练数据的权值分布,让其服从均匀分布。

(2)学习具有权值分布的训练数据集Dm (m= 1…M),得到基本的分类器 。计算 在训练数据集上的分类误差率。

 也就是分类错误样本的个数。(因为开始服从均匀分布)。

(3)计算 的系数,也就是弱分类器的权值。 可以看出分类错误样本的个数越多弱分类器的权值就越小,说明分类器的分类能力越差。

(4)更新训练数据集的权值分布。

由上述公式可以看出,可以增大分类错误样本的权值,突出分类错误的样本再进行分类。

(5)弱分类器的权值加权得到最终的分类器。

简单的原理如上文所述,详细原理可以查看李航版的《统计机器学习方法》。下面详细介绍如何才能训练一个合适的opencv分类器。

整个训练过程分为以下几步:

创建样本

     样本分为正、负两类。其中正样本就是我们要检测目标样本。因为我要检测车轮所以,我的正样本就是车轮。负样本就是其他任意的图片,经个人实验发现负样本跟正样本相关训练出的分类器分类效果比较好。(诸如,我的正样本是车轮,负样本是街道,道路,车身等)。

所有正样本统一大小40*40放在相应的文件夹下。

负样本的数量大于正样本数量放在相应的文件夹下。

正样本应该进行分割,使只包含有目标物。

一、所有的正样本放在pos文件夹下,负样本放在neg文件加下。

    文件中的所有图片,生成统一大小(40*40)保存到文件中:代码地址:Here。

    图片生成info.txt文件的代码,地址:Here。

二、分别为正负样本创建描述文件。

     A.  为正样本创建描述文件格式文件info.txt,并且把这个文件放在与样本图片同一目录下,例如我的目录为:             E:AdeskCpp-Primerharr-likepospos.txt (文件名改为:pos.txt)

     B.  为负样本创建集合文件格式文件neg.txt, 并且把这个文件放在与样本图片同一目录下,例如我的目录为:             E:AdeskCpp-Primerharr-likenegneg.txt。

三、创建正样本。

    Opencv2.4.8自带的分类器在D:opencvbuildx86vc10bin目录下。

    输入opencv_createsamples.exe回车就可以得到训练需要的参数列表。按照输入即可,我创建600个正样本。如下:

-info E:AdeskCpp-Primerharr-likepospos.txt -vec E:AdeskCpp-Primerharr-likepospos.vec -num 2000 -w 40 -h 40

    正样本创建完毕。开始训练分类器。

四 训练opencv自带的分类器。

    输入opencv_haartraining.exe(回车)同样可以得到训练需要的参数列表。

本人输入以下参数列表开始训练。

    -data E:AdeskCpp-Primerharr-likedt -vec E:AdeskCpp-Primerharr-likepospos.vec -bg E:AdeskCpp-Primerharr-likenegneg.txt -npos 1500 -nneg 4500 -nstages 2 -nsplits 5 -mem 4096 -nonsym -w 40 -h 40

    经验证正负样本数目在1:3的时候训练效果比较好。当然训练层数越多越好,我这儿只是训练了16层。如果训练过程中出现卡在某一层。有以下原因和解决方案。

是负样本有问题,解决方案(成功通过): 1。卡在某一层后,按ctrl c结束 2。更新你的负样本 3。不要删除已经训练出的cascade 4。继续训练,请注意是否要改动-nneg参数

    -mem 是训练时要求所占内存的电脑内存是4G所以我这儿写的是2048.具体看自己实现。

    训练完毕后会在文件夹下面发现一个dt.xml文件说明你训练成功。可以进入测试环节了。

    当然opencv自带的分类器作为入门的检测器有很多缺点,检测不是很准确,训练过程耗时太长等等。因此下面将介绍一个更好的检测器给大家。

在这两天的实验过程中发现的问题及解决方法

    问题1:若生成正样本是5000个时,训练正样本时全部都用完的话,会出现没法提取正样本的错误。

解决方法每次训练样本时都要比生成的正样本少200~300个例如我实验的时候就用4700个正样本。

    问题2,若在一个地方停止2,3个小时没动静

估计是负样本不足造成的。利用ctrl c指令中断重新进行训练增加负样本的数目及多样性。可以生成分辨率不同的分类器这样子分类器就会具有尺度不变性。

测试:

也可以用opencv的cvHaarDetectObjects函数进行检测:

代码语言:javascript复制
  CvSeq* faces = cvHaarDetectObjects( img, cascade, storage,1.1, 2, CV_HAAR_DO_CANNY_PRUNING,cvSize(40, 40) ); 

训练:

代码语言:javascript复制
// opencv_haartraining
-data E:AdeskCpp-Primerharr-likedt1 -vec E:AdeskCpp-Primerharr-likepospos.vec -bg E:AdeskCpp-Primerharr-likenegneg.txt -npos 3000 -nneg 9000 -nstages 10 -nsplits 2 -mem 6144 -nonsym -w 40 -h 40


// opencv_traincascade
-data E:AdeskCpp-Primerharr-likedt -vec E:AdeskCpp-Primerharr-likepospos.vec -bg E:AdeskCpp-Primerharr-likenegneg.txt -numPos 5000 -numNeg 9000 -numStages 8 -minHitRate 0.999 -precalcValbufSize 2048 -precalcdxBufSize 2048 -w 40 -h 40

opencv_traincascade测试:

代码语言:javascript复制
CascadeClassifier *face_cascade;
 vector<Rect> faces;
 
   face_cascade->detectMultiScale(frame_gray, faces, 1.1, 2, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));
 

测试代码:地址:Here。

0 人点赞