opencv cascade级联分类器的训练

2018-07-05  本文已影响1896人  Mr_Bluyee

充电站特征训练项目源码

介绍:

        Cascade即为级联,在网络WAN口级联、数据库信息间级联以及电路连接中的级联等等当中,级联都有一种隐性的意义——一种一对多的关系。一是一种输入,一类划分,一个触发,一次动作。多是多方参与,多种途径,多个标准,多个答案。Opencv cascade 是一次决断,多方铭鉴。如果我能找到99.9%的目标分类,那错误的分类中哪怕有50%误入结果,20轮之后也将不足为惧:20级的级联足够在99.9%变成99%的过程中,把50%变成0.0001%。这就是级联,或者说表现成的决策树。让每一个强分类器依次进行决策,被认为是正确的就将向下传递,错误的则被直接抛弃。再配合权重改变样本的分布,训练,上场,一锤定音。当AdaBoost遇见Cascade(浅谈级联分类)

基于Haar特征的级联分类器:

        Haar分类器、特征与其算法

        Haar分类器有两个体系,训练的体系和检测的体系。

        级联分类器:Haar分类器:训练出多个强分类器将它们强强联手,最终形成正确率很高的级联分类器就是最终目标Haar分类器。

        检测体系是以现实中很大一副图片作为输入,然后对图片中进行多区域,多尺度的检测,所谓多区域,是要对图片划分多块,对每个块进行检测,由于训练的时候一般图片都是20*20左右的小图片,所以对于大的特征,还需要进行多尺度的检测。多尺度检测一般有两种策略,一种是不改变搜索窗口的大小,而不断缩放图片,这种方法需要对每个缩放后的图片进行区域特征值的运算,效率不高,而另一种方法,是不断初始化搜索窗口size为训练时的图片大小,不断扩大搜索窗口进行搜索。在区域放大的过程中会出现同一个特征被多次检测,这需要进行区域的合并。无论哪一种搜索方法,都会为输入图片输出大量的子窗口图像,这些子窗口图像经过筛选式级联分类器会不断地被每个节点筛选,抛弃或通过。Haar级联分类器原理

Opencv的cascade分类器:

CascadeClassifier为OpenCV中cv namespace下用来做目标检测的级联分类器的一个类。该类中封装的目标检测机制,简而言之是滑动窗口机制+级联分类器的方式。OpenCV的早期版本中仅支持haar特征的目标检测,分别在2.2和2.4.0(包含)之后开始支持LBP和HOG特征的目标检测。opencv的cascade分类器源码分析

Opencv traincascade训练工具的使用:

opencv用户指南

工具所在文件位置:

opencv安装目录\opencv\build\x64\vc15\bin

1.制作正样本

我们训练了两种分类器,一大一小,大的正样本原图:

大的正样本 小的正样本,为大的里面的一部分

将上图旋转4个方向得到正样本4张原图,其样本分辨率设置为50*50。

正样本四张原图

该文件夹下的positive_sample1.txt为正样本描述文件,内容为:

正样本描述文件内容

其中,1.jpg为图片名,1为图片中的正样本数,0,0,50,50,为正样本所在图片中的像素位置。

准备负样本,即为不包含正样本元素的背景图片,我们采集了航拍的图片作为负样本,共273张,分辨率统一调整为1920X1080。(负样本选择要慎重,之前随机添加过多杂乱的背景图片,导致训练后的识别效果不好,表现为较难识别出目标)

背景航拍图片

负样本文件夹里也有描述文件,里面只要添加上图片的文件名即可。

负样本描述文件内容

文件名可以采用批量命名工具。

制作正样本用的是opencv_createsamples.exe这一工具,它的输出为以 *.vec 为扩展名的文件,该文件以二进制方式存储图像,能够被 opencv_haartraining 和 opencv_traincascade 程序支持。

命令行参数:

-vec输出文件,内含用于训练的正样本。

-img输入图像文件名(例如一个公司的标志)。

-bg背景图像的描述文件,文件中包含一系列的图像文件名,这些图像将被随机选作物体的背景。

-num生成的正样本的数目。

-bgcolor背景颜色(目前为灰度图);背景颜色表示透明颜色。因为图像压缩可造成颜色偏差,颜色的容差可以由 -bgthresh 指定。所有处于 bgcolor-bgthresh 和 bgcolor+bgthresh 之间的像素都被设置为透明像素。

-bgthresh-inv如果指定该标志,前景图像的颜色将翻转。

-randinv如果指定该标志,颜色将随机地翻转。

-maxidev前景样本里像素的亮度梯度的最大值。

-maxxangleX轴最大旋转角度,必须以弧度为单位。

-maxyangleY轴最大旋转角度,必须以弧度为单位。

-maxzangleZ轴最大旋转角度,必须以弧度为单位。

-show很有用的调试选项。如果指定该选项,每个样本都将被显示。如果按下 Esc 键,程序将继续创建样本但不再显示。

-w输出样本的宽度(以像素为单位)。

-h输出样本的高度(以像素为单位)。

        创建样本的流程如下: 输入图像沿着三个轴随机旋转。旋转的角度由 -max?angle 限定。然后像素的亮度值位于 [bg_color-bg_color_threshold; bg_color+bg_color_threshold]范围的像素被设置为透明像素。将白噪声加到前景图像上。如果指定了 -inv ,那么前景图像的颜色将被翻转。如果指定了 -randinv ,程序将随机选择是否将颜色进行翻转。任选背景图像,将获得的前景图像放到背景图像上,并将图像调整到 -w 和 -h 指定的大小。最后将图像存入vec文件,vec文件名由命令行参数 -vec 指定。

        正样本也可从一系列事先标记好的图像中创建。标记信息可以存储于一个文本文件,与背景描述文件类似。文件中的每行对应一个图像文件。每行的第一个元素为图像文件名,后面是物体的数目,最后是物体位置和大小的描述 (x, y, width, height)。

        -info 、-img是两种不同的制作正样本的方式,是二选一的。-info 是从描述文件里提取出样本,而不对其做任何调整与变化,最后正样本的数目就是描述文件里的正样本的数目,不会增加。-img是从一张图片创建正样本,可叠加不同的负样本背景,旋转不同的角度,以及颜色的翻转变化,可以指定生成的正样本数。

新建一个bat文件(create_positve_samples.bat),内容如下:

opencv_createsamples.exe -info source_positive_sample1_pic\positive_sample1.txt -vec positive_samples_vec\positive_sample1_self.vec -h 50 -w 50 -num 4 -show

opencv_createsamples.exe -info source_positive_sample2_pic\positive_sample2.txt -vec positive_samples_vec\positive_sample2_self.vec -h 50 -w 50 -num 4 -show

opencv_createsamples.exe -img source_positive_sample1_pic\1.jpg -vec positive_samples_vec\positive_sample1_1.vec -h 50 -w 50 -bg negative_samples_pic\negative_samples.txt -num 125 -maxxangle 1.1 -maxyangle 1.1 -maxzangle 0.5 -bgcolor 0 -bgthresh 0 -maxidev 40 -show

opencv_createsamples.exe -img source_positive_sample1_pic\2.jpg -vec positive_samples_vec\positive_sample1_2.vec -h 50 -w 50 -bg negative_samples_pic\negative_samples.txt -num 125 -maxxangle 1.1 -maxyangle 1.1 -maxzangle 0.5 -bgcolor 0 -bgthresh 0 -maxidev 40 -show

opencv_createsamples.exe -img source_positive_sample1_pic\3.jpg -vec positive_samples_vec\positive_sample1_3.vec -h 50 -w 50 -bg negative_samples_pic\negative_samples.txt -num 125 -maxxangle 1.1 -maxyangle 1.1 -maxzangle 0.5 -bgcolor 0 -bgthresh 0 -maxidev 40 -show

opencv_createsamples.exe -img source_positive_sample1_pic\4.jpg -vec positive_samples_vec\positive_sample1_4.vec -h 50 -w 50 -bg negative_samples_pic\negative_samples.txt -num 125 -maxxangle 1.1 -maxyangle 1.1 -maxzangle 0.5 -bgcolor 0 -bgthresh 0 -maxidev 40 -show

opencv_createsamples.exe -img source_positive_sample2_pic\1.jpg -vec positive_samples_vec\positive_sample2_1.vec -h 50 -w 50 -bg negative_samples_pic\negative_samples.txt -num 125 -maxxangle 1.1 -maxyangle 1.1 -maxzangle 0.5 -bgcolor 0 -bgthresh 0 -maxidev 40 -show

opencv_createsamples.exe -img source_positive_sample2_pic\2.jpg -vec positive_samples_vec\positive_sample2_2.vec -h 50 -w 50 -bg negative_samples_pic\negative_samples.txt -num 125 -maxxangle 1.1 -maxyangle 1.1 -maxzangle 0.5 -bgcolor 0 -bgthresh 0 -maxidev 40 -show

opencv_createsamples.exe -img source_positive_sample2_pic\3.jpg -vec positive_samples_vec\positive_sample2_3.vec -h 50 -w 50 -bg negative_samples_pic\negative_samples.txt -num 125 -maxxangle 1.1 -maxyangle 1.1 -maxzangle 0.5 -bgcolor 0 -bgthresh 0 -maxidev 40 -show

opencv_createsamples.exe -img source_positive_sample2_pic\4.jpg -vec positive_samples_vec\positive_sample2_4.vec -h 50 -w 50 -bg negative_samples_pic\negative_samples.txt -num 125 -maxxangle 1.1 -maxyangle 1.1 -maxzangle 0.5 -bgcolor 0 -bgthresh 0 -maxidev 40 -show

pause

-img样本数设置为125,maxxangle,maxyangle设置为1.1,maxzangle设置为0.5。为什么这样设置?因为一张图片设置的旋转角度不宜过大,过大会扭曲特征,极端情况下会出现旋转到只看到一条线的情况,而这种样本是不应该的。所以maxangle我们基本设置的是默认参数,这个值是弧度值。而旋转角度变化不大的话,只用一个角度的样本很难生成各种角度的正样本,因此,我们才准备了四个方向角度的四张图片。生成的正样本为灰度图像,如下所示的两个正样本:

正样本1 正样本2

生成的文件如下:

生成vec文件

将1、2、3、4与self.vec文件合为一个vec文件(collection.vec),这里使用工具mergevec.exe。同样,先编写描述文件(vec_collection1.txt),就是列出要合并的vec文件名,内容如下:

描述文件内容

新建一个bat文件(mergevec_collection.bat),内容如下:

mergevec.exe vec_collection1.txt positive_sample1_collection.vec

mergevec.exe vec_collection2.txt positive_sample2_collection.vec

pause

第一个参数为描述文件,第二个为合并后生成的文件名。至此,正样本制作完成,然后要记得collection.vec里一共有多少个正样本,4*125+4=504个。

2.训练分类器

        opencv提供了两个训练工具, opencv_traincascade 和 opencv_haartraining 。它们都可用来训练一个级联分类器,我们使用opencv_traincascade.exe。opencv_traincascade.exe有许多命令参数,这里只介绍常用的:

通用参数:

-data目录名,如不存在训练程序会创建它,用于存放训练好的分类器。(实际训练之前必须创建好他,否则在写训练好的文件时程序会报错)

-vec包含正样本的vec文件名(由 opencv_createsamples 程序生成)。

-bg背景描述文件,也就是包含负样本文件名的那个描述文件。(背景描述文件必须和opencv_traincascade.exe在同一文件夹下,否则开始运行训练时程序会报错)

-numPos每级分类器训练时所用的正样本数目。

-numNeg每级分类器训练时所用的负样本数目,可以大于 -bg 指定的图片数目。

-numStages训练的分类器的级数,默认20级。

-precalcValBufSize缓存大小,用于存储预先计算的特征值(feature values),单位为MB。

-precalcIdxBufSize缓存大小,用于存储预先计算的特征索引(feature indices),单位为MB。内存越大,训练时间越短。

-baseFormatSave这个参数仅在使用Haar特征时有效。如果指定这个参数,那么级联分类器将以老的格式存储。

级联参数:

-stageType级别(stage)参数。目前只支持将BOOST分类器作为级别的类型。

-featureType<{HAAR(default), LBP}>特征的类型: HAAR - 类Haar特征; LBP - 局部纹理模式特征。

-w -h训练样本的尺寸(单位为像素)。必须跟训练样本创建(使用 opencv_createsamples 程序创建)时的尺寸保持一致。

其中大部分参数都可以用默认参数,最要注意的是正负样本数的选择,有这样一个计算公式:

vec-file number >= (numPos + (numStages-1) * (1 – minHitRate) * numPos) + S

vec-file number 就是我们的正样本总数,numstages=20,minHitRate=0.995,S 表示负样本总数,正负样本比需要控制在大于2:1。

训练时,每一层所需的正样本数会逐渐增加,故开始配置正样本参数时,不可以填入总的正样本数,否则训练到后面需要的正样本数超出所拥有的正样本数时程序会报错。大致填入所拥有的正样本数的90%的数目即可。

正负样本数不宜过多,否则内存消耗大,而且训练异常缓慢。我们开了vps来训练样本,8核cpu,40G内存。正负样本数适宜的设置约为500:1000这样。

新建一个bat文件(trancascade_sample1.bat),内容如下:

opencv_traincascade.exe -data data1 -vec positive_samples_vec\positive_sample1_collection.vec -bg bg.txt -numPos 470 -numNeg 1000 -w 50 -h 50

pause

若内存比较多,可配置BufSize那两项,可以缩短训练所需时间。 -precalcValBufSize  -precalcIdxBufSize 

bg.txt即为负样本的描述文件,负样本用的与制作正样本所用的负样本一致。样本大小为50*50。启动运行时,如下图所示:

启动运行时

        当之前的强分类器对负样本集内的样本全部分类正确时会出现死循环。因为只要有一个样本会被错分为正样本,那么通过 count次扫描整个负样本集就能得到 count 个负样本,当然这 count 个负样本实际上就是一个负样本的 count 个拷贝。为避免这些情况的发生,负样本集中的样本数需要足够多。在负样本图像大小与正样本大小完全一致时,假设最终的分类器虚警率要求是falsealarm,参加训练的负样本要求是 count 个,则需要的负样本总数可计算如下: TotalCount = count / falsealarm以 Rainer Lienhart 的文章中的一些参数为例,falsealarm=0.5^20=9.6e-07, count=3000,则 TotalCount=3000/(0.5^20)= 3,145,728,000=31 亿。在程序第一次运行时,只要负样本集中有 count 个样本,就一定能取出 count 个负样本。在以后运行到此时,有可能取不到 count 个样本,因为必须是用前面的级联强分类器分类为正样本的样本(即分类错误的样本)才会被取出作为下一个强分类器的负样本输入。

opencv traincascade.exe在提取文件,计算特征时,使用多核,开始训练时占用不高。故cpu核数对缩短训练的时间的贡献不是特别大,如下图所示:

提取特征时,使用多核 训练时

训练结束后如下图所示:

训练完成

训练完成后,在指定生成的文件夹下会有如下文件:

训练生成的文件

其中,cascade.xml文件即为最终的训练结果,即可拿来进行目标检测。

上一篇下一篇

猜你喜欢

热点阅读