Ubuntu利用opencv训练自己的xml文件
先前在windows系统训练的xml,在应用的时候效果不是很好,检测有很大的误差,这里有几点经验(也是出问题的时候,在网上找到的解决方法及理论知识)。
---采集正负样本的数量及尺寸---
1.数量:
正样本500,负样本1500(如果在训练时要用到500正样本和1500负样本,那么在采集的时候需要都要多采集一些,大概多采100张左右)
为什么要多采?
因为在训练时,要填写-numPos 和 -numNeg这两个参数,而根据实际训练情况,要满足以下要求:
实际准备的正样本数量(读入vec-file的正样本数) >= numPos + (numStage - 1) * numPos * (1 - minHitRate)
vec-file的正样本数就是根据原始的正样本生成的,所以如果-numPos设为500的话,vec-file的数量就需要大一些,如果较小的话就会出现(Bad argument < Can not get new positive sample. The most possible reason is insufficient count of samples in given vec-file.)的错误。
相关参数:
vec-fil:通过opencv_createSamples利用pos.txt生成的pos.vec文件(正样本数就是pos.txt读取的原始正样本的数量)
numPos:每一级stage训练所需的正样本数目(本人原始正样本数为565,那numPos就设置为500)
numStage:训练的级数,相当于keras中的epoch,默认为20,本人设置为15( stage数不是越大越好,过大可能会导致过拟合 )
minHitRate:分类器的每一级希望得到最小检测率(即正样本被判断有效的比例),最优设置0.9999
2.尺寸:
正样本( 50px * 50px )
正样本的尺寸设置为20*20 / 30*30 / 50*50都行,但不能太大,如果太大就会导致( OpenCV Error: Insufficient memory (Failed to allocate 65408 bytes) in unknown function )内存分配不够的错误。
负样本( 300px * 300px )
负样本的尺寸必须要大于正样本的6倍或者更大。
因为首先我们要知道训练程序中写的numNeg参数表示每级训练用到的负样本数,本人把它设置为1500。其实这个numNeg的大小和原始负样本数量没有任何关联, 因为numNeg是通过滑动窗口在原始负样本上不断滑动采集,得到的预处理负样本图像的数量(滑动窗口的大小就是正样本的大小,这里是50*50)
负样本的尺寸如果不够大,或者和正样本一样大,滑动窗口就无法在原始负样本上滑动来采集足够多的训练图像,再加上如果收集到的原始负样本的数量可能并不比正样本多多少,也许就是3、4倍。这样的话就会导致( 执行opencv_traincascade训练程序过程中中断 )的错误,同时会报(Train dataset for temp stage can not be filled. Branch training terminated。)这时我们发现训练图中的FA( FalseAlarm,虚警率 )为0,表示负样本已全部被正确分类了,也就不会有负样本继续参与下一轮的训练了,所以就退出了。
所以在准备原始负样本的时候一定要保证尺寸足够大,同时包含的内容足够复杂。
---numPos 和 numNeg的比例---
numPos : numNeg = 1:3,这是最优的比例
1. 当numPos和numNeg比例接近的时候1:1,对numNeg内负样本的看中程度很低,在实际的生活中负样本肯定远远多于正样本。
2. 当numPos和numNeg比例较大的时候1:10,对numNeg内负样本多于看中而忽略了正样本的统计特性,造成正样本权重总和很小,当权重小于一定程度的时候可能很大一部分正样本都不参与训练了。
--- Haar和LBP特征 ---
基于LBP特征的分类器几乎能和基于Harr特征的分类器拥有一样的性能,并且由于LBP属于整数型的特征,所以在训练的时候要比Haar特征快得多。
所以在训练的参数中要添加 -featureType LBP,这样能加快训练速度
以上是在整个准备和训练期间需要注意的事项,现在正式开始。
系统:Ubuntu16.04
opencv版本:opencv3.2.0
python版本:python2.7
opencv本人用的版本是源码编译的opencv3.2.0,安装链接已给出,进入python后>>>import cv2不报错,即为安装成功。
--- 数据准备 ---
新建一个/my_xml文件夹作为项目根目录,将正样本放入/my_xml/pos中,将负样本放入/my_xml/neg中。
还需要opencv_createsamples 和 opencv_traincascade这两个程序,在/usr/local/bin中可以找到,通过( cp 程序路径 目标路径 )复制过来就OK了,当前目录如下:
---生成样本路径文件---
生成正样本的pos.txt路径文件,命令行进入根目录运行:
ls pos/*.*>pos.txt
然后将刚生成的pos.txt文件在sublime中打开,按住鼠标滚轮,往下拖,即可选中当前列;按一下键盘的“END”键,光标即可跳转到字符串尾部,效果如下:
【1 :该样本数目为1;0 0 :表示样本起始坐标;500 500 : 表示样本宽高】生成neg.txt同理,不过格式稍有不同,最终两个文件的效果如下:
---生成正样本的vec文件---
命令行进入根目录,运行以下代码:
opencv_createsamples -vec pos.vec -info pos.txt -bg neg.txt -w 50 -h 50
出现以下效果,同时在根目录生成pos.vec文件,即为成功:
--- 开始训练 ---
开始训练前,在根目录底下新建一个/data目录,用于存放训练完毕的xml文件,当前根目录效果如下:
运行以下代码,开始训练
opencv_traincascade -data data -vec pos.vec -bg neg.txt -numPos 500 -numNeg 1500 -numStages 15 -featureType LBP -w 50 -h 50 -minHitRate 0.9999 -maxFalseAlarmRate 0.5
相关参数:
-data : 存放xml文件的目录
-vec : 正样本vec文件源
-bg : 负样本路径txt文件
-numPos : 正样本数量
-numNeg : 负样本数量
numStages:训练分类器的级数
-featureType: 默认使用Haar特征,还有LBP和HOG可供选择(HOG为opencv2.4.0版本以上)
-w -h : 样本宽高
-minHitRate :分类器的每一级希望得到最小检测率(即正样本被判断有效的比例)
-maxFalseAlarmRate:分类器的每一级希望的最大误检率(负样本判定为正样本的概率)
-mode: 选择训练中使用的Haar特征类型。BASIC只使用右上特征,ALL使用所有右上特征及45度旋转特征(使用Haar特征的前提下,否则不使用此参数)
出现以下画面,表示训练顺利进行:
--- 验证效果 ---
迭代玩15次后,在/data目录下生成了一堆xml文件,我们选用cascade.xml
python代码如下:
效果如下:
参考文章:
https://blog.csdn.net/u014587123/article/details/78507649?locationNum=6&fps=1