采用opencv_cascadetrain进行训练的步骤及注意事项
OpenCV中有两个程序可以训练级联分类器: opencv_haartraining 和opencv_traincascade。opencv_traincascade 是一个新程序,使用OpenCV 2.x API 以C++ 编写。这二者主要的区别是 opencv_traincascade 支持 Haar、Hog和 LBP(Local Binary Patterns) 三种特征,并易于增加其他的特征。与Haar特征相比,LBP特征是整数特征,因此训练和检测过程都会比Haar特征快几倍。LBP和Haar特征用于检测的准确率,是依赖训练过程中的训练数据的质量和训练参数。训练一个与基于Haar特征同样准确度的LBP的分类器是可能的。
opencv_traincascade and opencv_haartraining 所输出的分类器文件格式并不相同。注意,新的级联检测接口(参考 objdetect 模块中的 CascadeClassifier 类)支持这两种格式。 opencv_traincascade 可以旧格式导出训练好的级联分类器。但是在训练过程被中断后再重启训练过程, opencv_traincascade and opencv_haartraining 不能装载与中断前不同的文件格式。
opencv_traincascade 程序使用TBB来处理多线程。如果希望使用多核并行运算加速,请使用TBB来编译OpenCV。还有一些与训练相关的辅助程序。
opencv_createsamples 用来准备训练用的正样本数据和测试数据。 opencv_createsamples 能够生成能被 opencv_haartraining 和 opencv_traincascade 程序支持的正样本数据。它的输出为以 *.vec 为扩展名的文件,该文件以二进制方式存储图像。
opencv_performance 可以用来评估分类器的质量。它读入一组标注好的图像,运行分类器并报告性能,如检测到物体的数目,漏检的数目,误检的数目,以及其他信息。
http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/user_guide/ug_traincascade.html
http://blog.csdn.net/delltdk/article/details/9186875
1 建立样本集pos和neg
pos中存放正样本的图像,可以是一张图像或多张图像。neg中存放包含负样本的图像,可以是任意图像,但是这些图像中不能包含待检测的物体。
注意:
一般需要一个很大的负样本库送给训练程序进行训练。如果是绝对刚性的物体,如OpenCV的标志,只有一张正样本图像,那么可以通过对物体图像的随机旋转、改变标志亮度以及将标志放在任意的背景上而获得大量的正样本;如果是人脸,需要几百甚至几千个正样本。在待检测物体是人脸的情况下,需要考虑所有的人种、年龄、表情甚至胡子的样式。
2 生成正\负样本描述文件negdata.txt
(1) 负样本描述文件negdata.txt
在命令行窗口输入“cd d:\%....%\pos”路径切换到neg文件夹下,输入“dir/b>negdata.txt”就会在neg文件夹下生成描述文件negdata.txt,存放neg中所有图片的文件名,注意要去掉最后的negdata.txt 。
注意:
如果把negdata.txt保存在neg文件夹外面,需要在每一行外面添加相对路径或绝对路径来指出样本的所在位置。一种方法是将negdata.txt 文件中的内容复制到word中,使用替换功能实现快速修改。neg替换为neg\neg
(2) 正样本描述文件posdata.txt
与建立negdata.txt一样建立posdata.txt,只不过在正样本描述文件中需要指出目标在每个样本中的数量和位置如pos\1.bmp 1 x1 y1 x2 y2,其中(x1,y1,x2,y2)为目标所在的矩形框,又如pos\1.bmp2 x1 y1 x2 y2 x1’ y1’ x2’ y2’
因为我们准备的正样本基本都是目标,因此只需在文件名后增加1 0 0 width height即可。
注意:
1若正样本图像是不同尺寸的,一方面可以使用ImageResize或matlab将图像统一成同一尺寸在生成posdata.txt,或程序ImageToTxt直接生成具有不同尺寸图像的正样本描述文件。在此阶段不归一化的话,后续生成.vec文件的时候在程序中自动归一化。
2样本描述文件与图像要一致,可以存在图像但没有写在描述文件中,即有多余的图像,但千万不要在描述文件中写不存在的图像。
问题:
归一化尺寸的方法是否对训练结果有影响? opencv_createsamples 采用何种方法进行归一化?
sample = cvCreateImage( cvSize(winwidth, winheight ), IPL_DEPTH_8U, 1 );
fscanf( info, "%d %d %d%d", &x, &y, &width, &height )
cvSetImageROI( src, cvRect( x, y, width,height ) );
cvResize( src, sample,
width >=sample->width && height >= sample->height ? CV_INTER_AREA :CV_INTER_LINEAR );
CV_INTER_NN 最近邻插值
CV_INTER_LINER 双线性插值,缺省情况
CV_INTER_AREA 使用像素关系重采样,当图像缩小时候可以避免波纹出现,当图像方法时类似CV_INTER_NN
CV_INTER_CUBIC 立方插值
3 生成.vec文件
生成的正样本数目以及随机的程度都可以通过 opencv_createsamples 的命令行参数控制。
使用create.dat调用%Opencv%\vs2008\bin\Release\ opencv_createsamples.exe
在createsamples.cpp中查阅参数设置
-info 输入正样本描述文件,默认NULL
-img 输入图像文件名,默认NULL
-bg 负样本描述文件,文件中包含一系列的被随机选作物体背景的图像文件名,默认NULL
-num 生成正样本的数目,默认1000
-bgcolor 背景颜色,表示透明颜色,默认0
-bgthresh 颜色容差,所有处于bgcolor-bgthresh和bgcolor+bgthresh之间的像素被置为透明像素,也就是将白噪声加到前景图像上,默认80
-inv 前景图像颜色翻转标志,如果指定颜色翻转,默认0(不翻转)
-randinv 如果指定颜色将随机翻转,默认0
-maxidev 前景图像中像素的亮度梯度最大值,默认40
-maxxangle X轴最大旋转角度,以弧度为单位,默认1.1
-maxyangle Y轴最大旋转角度,以弧度为单位,默认1.1
-maxzangle Z轴最大旋转角度,以弧度为单位,默认0.5
输入图像沿着三个轴进行旋转,旋转角度由上述3个值限定。
-show 如果指定,每个样本都将被显示,按下Esc键,程序将继续创建样本而不在显示,默认为0(不显示)
-scale 显示图像的缩放比例,默认4.0
-w 输出样本宽度,默认24
-h 输出样本高度,默认24
-vec 输出用于训练的.vec文件,默认NULL
将正样本描述文件中的正样本转换为灰度图像并缩放到-w-h尺寸存入vec文件中。
(1)如果设置-img和-vec
调用cvCreateTrainingSamples,采用一张图像创建训练样本
(2)如果设置-img、-bg和-info
调用cvCreateTestSamples,采用一张图像创建测试样本。-bg在这里又有什么作用?目的是作为背景创建测试图像。
(3)如果设置-info和-vec(采用正样本描述文件中的图像创建训练样本)
调用cvCreateTrainingSamplesFromInfo,在cvCreateTrainingSamplesFromInfo中将读取样本,并resize后调用icvWriteVecHeader和icvWriteVecSample创建vec文件。
(4)如果只设置-vec(只显示vec文件中的样本)
调用cvShowVecSamples查看和检查保存在vec文件中正样本
上述参数在create.dat中设置好,最后有一个pause,等待显示结果:Done.Created num samples
4 训练过程
使用train.dat调用%Opencv%\vs2008\bin\Release\ opencv_traincascade.exe
在traincascade.cpp中查阅参数设置
1基本参数
-data 目录名,存放训练好的分类器,如果不存在训练程序自行创建
-vec 正样本.vec文件,由opencv_createsamples生成
-bg 负样本描述文件
-numPos 每级分类器训练时所用到的正样本数目
-numNeg 每级分类器训练时所用到的负样本数目,可以大于-bg指定的图片数目
-numStages 训练分类器的级数
-precalcValBufSize 缓存大小,用于存储预先计算的特征值,单位MB
-precalcIdxBufSize 缓存大小,用于存储预先计算的特征索引,单位M币
-baseFormatSave 仅在使用Haar特征时有效,如果指定,级联分类器将以老格式存储
2级联参数cascadeParams
-stageType 级联类型,staticconst char* stageTypes[] = { CC_BOOST };
-featureType 特征类型,staticconst char* featureTypes[] = { CC_HAAR, CC_LBP, CC_HOG };
-w
-h 训练样本的尺寸,必须跟使用opencv_createsamples创建的训练样本尺寸保持一致
3Boosted分类器参数stageParams
-bt Boosted分类器类型
DAB-discrete Adaboost, RAB-RealAdaboost, LB-LogiBoost, GAB-Gentle Adaboost
-minHitRate 分类器的每一级希望得到的最小检测率,总的最大检测率大约为
min_hit_rate^number_of_stages
-maxFalseAlarmRate 分类器的每一级希望得到的最大误检率,总的误检率大约为
max_false_rate^number_of_stages
-weightTrimRate Specifies whether trimming should beused and its weight. 一个还不错的数值是0.95
-maxDepth 弱分类器的最大深度,一个不错数值是1,二叉树
-maxWeightCount 每一级中弱分类器的最大数目
4Haar特征参数featureParams
-mode 训练过程使用的Haar特征类型,CORE-Allupright ALL-All Features BASIC-Viola
上述参数设置好后调用CvCascadeClassifier::train进行训练
将上述内容在train.dat中编辑好,运行即可。训练最终生成一个-data指定级联分类器的文件夹和一个cascade.xml文件,其余文件都是中间结果,当训练程序被中断之后,再重新运行训练程序将读入之前的训练结果,无需从头重新训练,训练结束后可以删除这些文件。
在cascade.xml文件中主要有stageType,featureType,width,height,stageParams,featureParams,stageNum,stages和features节点。
stages中的stage数目是自己设定的,每个stage又包含多个weakClassifiers,每个weakClassifier又包含一个internalNodes和一个leafValues。internalNodes中四个变量代表一个node,分别为node中的left/right标记,特征池中的ID和threshold。leafValues中两个变量代表一个node,分别为leftleaf和right leaf值。
features是分类器的特征池,每个Haar特征包含一个矩形rect和要提取的特征序号,每个Hog特征/LBP特征包含一个矩形。
注意:
1 包含负样本的图像一定不小于在create中设置的尺寸
负样本图像可以是不同的尺寸,但是图像尺寸应该比训练窗口的尺寸大,在使用负样本图像时,OpenCV自动从负样本图像中抠出一块和正样本同样大小的区域作为负样本。具体可查阅icvGetNextFromBackgroundData,具体抠图过程为:
1) 确定抠图区域的左上角坐标(Point.x, Point.y)
2) 确定一个最小缩放比例,使得原负样本图像缩放后恰好包含选中负样本区域
3) 对原负样本图象按计算好的缩放比例进行缩放
4) 在缩放后的图像上抠出负样本。
2 –numPos一般比实际正样本数量少200-300,-numNeg是否存在同样的情况?正负样本选择规则?
如果出现:训练停留在一个分类器长达几小时没有相应,问题出现在取负样本的那个函数 icvGetHaarTrainingDataFromBG中;只有当之前的强分类器对负样本集内的样本全部分类正确时才会出现死循环,因为只要有一个样本会被错分为正样本,那么通过count次扫描整个负样本集就能得到count个负样本,当然这count个负样本实际上就是一个负样本的count个拷贝。为避免这种情况,负样本集中的样本数需要足够多 。
不过此时的分类器已经完全额、可以使用,因为它的误检率已经很低,从实用性上时没有任何问题的。所以我们可以通过设置-nstages 这个参数来限制分类器级数,适当时候停止并生成xml文件。
从CvCascadeBoost::train中去查阅
函数 poscount= icvGetHaarTrainingDataFromVec( training_data, 0, npos,
(CvIntHaarClassifier*)tcc, vecfilename, &consumed )负责从正样本集*.vec 文件中载入 count(npos)个正样本。在程序第一次运行到此(即训练第一个分类器之前)时,只要正样本集中有 count 个样本,就一定能取出 count 个正样本。在以后运行到此时,有可能取不到 count 个样本,因为
必须是用前面的级联强分类器((CvIntHaarClassifier*) tcc)分类为正样本(即分类正确的样本)的样本才会被取出作为下一个强分类器训练样本,具体可参考 icvGetHaarTrainingData和icvEvalTreeCascadeClassifierFilter函数。
训练负样本,具体可参考icvGetHaarTrainingDataFromBG和icvEvalTreeCascadeClassifierFilter函数。
int icvGetHaarTrainingDataFromBG(CvHaarTrainingData* data, int first, int count,
CvIntHaarClassifier*cascade, double* acceptance_ratio, const char * filename = NULL )
传递返回值的 acceptance_ratio 参数记录的是实际取出的负样本数与查询过的负样本数(如果通过前面级联stage强分类器的负样本数很少时,那么程序会循环重复读取负样本,并用thread_consumed_count计数)之比(acceptance_ratio = ((double) count) / consumed_count),也就是虚警率,用于判断已训练的级联分类器是否达到指标,若达到指标,则停止训练过程。
注意函数 icvGetHaarTrainingData中一个主要的 For 循环:
for( i = first; i < first +count; i++ ) //共读取 count 个负样本,当读取不到
{ //这么多负样本时将出现死循环!
对上面代码中的注释有必要进一步说明一下:只有当之前的强分类器对负样本集内的样本全部分类正确时才会出现死循环。因为只要有一个样本会被错分为正样本,那么通过 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 亿。
函数 icvGetHaarTrainingDataFromBG ()负责从负样本集中载入 count 个负样本。在程序第一次运行到此(即训练第一个分类器之前)时,只要负样本集中有 count 个样本,就一定能取出 count 个负样本。在以后运行到此时,有可能取不到 count 个样本,因为必须是用前面的级联强分类器分类为正样本的样本(即分类错误的样本)才会被取出作为下一个强分类器的负样本输入。
对于int icvGetHaarTrainingData( CvHaarTrainingData* data,int first, int count,
CvIntHaarClassifier*cascade,
CvGetHaarTrainingDataCallbackcallback, void* userdata,
int*consumed, double* acceptance_ratio )
这个函数的解释:
这是个对于读取正负样本通用的函数,区别在于callback的调用。在这个函数中有个变量thread_getcount,表示将样本分为正样本的数目(不论这个样本是负样本还是正样本)。
传递返回值的 Consumed 参数表示为取 count 个正样本,查询过的正样本总数。对于负样本为空(null),没有返回值。
3 之前遇到过10*20的不能训练Hog特征的分类器?Hog特征是否存在尺寸限制?
查阅Hog特征的计算方法,Opencv中HogDescriptor
采用opencv_cascadetrain进行训练的步骤及注意事项相关推荐
- 四轴FPV手动训练进阶步骤
四轴FPV手动训练进阶步骤 1. 目的 2. 训练 2.1 基本操作训练 2.1.1 滞空训练 2.1.2 基本动作 2.1.3 位置保持 2.2 基本控制训练 2.2.1 转弯(Turn) 2.2. ...
- revit建筑样板_Revit出建筑施工图步骤及注意事项
大家知道一套完整的建筑施工图有图纸目录,建筑设计说明,工程做法表,平面图,立面图,剖面图及详图等组成,不同的图纸在Revit里出图的方式是不一样的. Revit里是可以直接出施工图的,而且不亚于CAD ...
- c语言实现1024点fft程序,数字信号处理的步骤与注意事项,并编写1024个采样点的FFT C语言程序...
数字信号处理的步骤与注意事项,并编写1024个采样点的FFT C语言程序 1. 数字信号处理 1.1 数字信号处理概述 数字信号处理是研究如何用数字或符号序列来表示信号以及如何对这些序列进行处理的一门 ...
- 发那科机器人电柜没电怎么回事_「维修篇」发那科FANUC机器人电路板维修步骤及注意事项...
机器人维修要说比较复杂是的什么,小编相信很多维修人员映入脑海的第一个几乎都是电路板了,电路板因其结构的特殊性,非常复杂也非常精细,在维修过程中通常需要借助专业维修工具才能进行维修.一些非专业维修人员可 ...
- 【电气专业知识问答】问:当发生直流系统接地故障,处理操作步骤和注意事项有哪些?
[电气专业知识问答] 问:当发生直流系统接地故障,处理操作步骤和注意事项有哪些? 答:当发出直流系统一点接地故障报警时,值长及运行人员应尽快查明故障回路.查找接地点,设法消除故障,不允许系统发生一点接 ...
- 如何开搓饵不掉钩_搓饵的制作步骤以及注意事项
作为钓鱼人,我们都知道搓饵用在钓深水.闹小鱼.钓大鱼的时候有良好的效果.那么一款状态合适的搓饵要怎么制作出来呢?笔者整理一些有关搓饵的资料,下面就给大家介绍下搓饵的制作步骤以及注意事项来了解一番. 一 ...
- ssh改造springboot微服务系统改造升级步骤及注意事项(一)
ssh改造springboot微服务系统改造升级步骤及注意事项(一) 本次系统改造是以目前市场较为前沿.主流的技术为标准进行改造.为了达到系统性能的提升.实现高并发.高可用以及增强系统可扩展性等目的. ...
- 系统改造升级步骤及注意事项(一)
系统改造升级步骤及注意事项(一) 本次系统改造是以汇中综合业务系统中的调度系统(Dispatch)为核心展开的全面升级,以目前市场较为前沿.主流的技术为标准进行改造.为了达到系统性能的提升.实现高并发 ...
- fpga烧写bin文件_Altera FPGA烧写步骤及注意事项_骏龙科技
Altera FPGA烧写步骤及注意事项 作者:Altera中国区代理――骏龙科技 由于Fiberhome在一些比较老的项目中使用了EPC1或者EPC1441一次性编程器件,不能进行重复编程,如果烧写 ...
最新文章
- flannel 概述 - 每天5分钟玩转 Docker 容器技术(58)
- JAVAOO 14 16章
- 2204 Problem A(水)
- Codefroces1077F2. Pictures with Kittens (hard version)
- 褚时健:现在的年轻人太急了,我快90了还在摸爬滚打
- 怎么改wps表格中折线图的横坐标?
- 电脑切换窗口快捷键_计算机二级常用快捷键
- php 取一条数据,php 读取txt 每次固定输出一条数据用什么方法实现?
- JavaScript常用算法 1
- MyEclipse10破解详细说明
- 笔记本显示电源已连接但是未充电的简单解决办法
- Hyperledger Fabric Peer的内部工作原理和实现方法
- Bouncing Ball (dp)
- 哔哩哔哩面试经验分享
- 启锐 588 打印机每次打印都流出一部分,没有重新切换纸张
- 【Linux进程概念】冯 诺依曼体系结构 操作系统 进程 fork 进程状态 优先级
- 如何将文字转图片?手把手教你转换
- 微信小程序,几行代码实现图片瀑布流
- 入侵特斯拉——智能汽车安全性分析
- 不入小程序,则为大笨熊