本节研究traincascade的opencv实现.
涉及的源代码位于:
sources\apps\traincascade traincascade实现
sources\modules\ml opencv machine learning部分
sources\data\vec_files\trainingfaces_24-24.vec 正样本
http://blog.csdn.net/njzhujinhua/article/details/38377191
【1】Cascade框架
首先从main入手
int main( int argc, char* argv[] ) { CvCascadeClassifier classifier; string cascadeDirName, vecName, bgName; int numPos = 2000; int numNeg = 1000; int numStages = 20; int precalcValBufSize = 256, precalcIdxBufSize = 256; bool baseFormatSave = false; CvCascadeParams cascadeParams; CvCascadeBoostParams stageParams; Ptr<CvFeatureParams> featureParams[] = { Ptr<CvFeatureParams>(new CvHaarFeatureParams), Ptr<CvFeatureParams>(new CvLBPFeatureParams), Ptr<CvFeatureParams>(new CvHOGFeatureParams) }; int fc = sizeof(featureParams)/sizeof(featureParams[0]); //略 classifier.train( cascadeDirName, vecName, bgName, numPos, numNeg, precalcValBufSize, precalcIdxBufSize, numStages, cascadeParams, *featureParams[cascadeParams.featureType], stageParams, baseFormatSave ); return 0; }
其中的CvCascadeParams 继承自ml的CvParams,
CvCascadeBoostParams 继承自ml的CvBoostParams后者则是CvDTreeParams的子类.
在CvCascadeBoostParams 中将boosttype设为了GENTLE,一类比较高效的AdaBoost
train的各参数:
cascadeDirName, 表示训练结果输出目录
vecName, 正样本的vec文件,由 opencv_createsamples 生成。正样本可以由包含待检测物体的一张图片生成,也可由一系列标记好的图像生成。
bgName, 背景图像的描述文件,文件中包含一系列的图像文件名,这些图像将被随机选作物体的背景
numPos, numNeg, 正负样本的个数
precalcValBufSize, 缓存大小,用于存储预先计算的特征值(feature values),单位为MB。
precalcIdxBufSize 缓存大小,用于存储预先计算的特征索引(feature indices),单位为MB。内存越大,训练时间越短。
numStages, 训练的分类器的级数
cascadeParams, 级联参数,除了默认值外,还可以通过参数指定. 其中stageType智能取值BOOST, featureType则支持haar,LBP,LOG
*featureParams[cascadeParams.featureType], 根据fratureType确定具体使用的FeatureParams
stageParams, boost分类器的参数,
-bt指定boosttype,取值
DAB=Discrete AdaBoost
RAB = Real AdaBoost,
LB = LogitBoost,
GAB = Gentle AdaBoost,默认为GENTLE AdaBoost
-minHitRate
分类器的每一级最小检测率, 默认0.995。总的检测率大约为 min_hit_rate^number_of_stages。
-maxFalseAlarmRate
分类器的每一级允许最大FPR,默认0.5。总的为 max_false_alarm_rate^number_of_stages.
-weightTrimRate
样本权重按大小序累计超过此致的样本保留进入下一轮训练. 默认0.95。 见CvBoost::trim_weights
-maxDepth
弱分类器树最大的深度。默认是1,是二叉树(stumps),只使用一个特征。
-maxWeakCount
每一级中的弱分类器的最大数目。默认100
DAB=Discrete AdaBoost
RAB = Real AdaBoost,
LB = LogitBoost,
GAB = Gentle AdaBoost,默认为GENTLE AdaBoost
-minHitRate
分类器的每一级最小检测率, 默认0.995。总的检测率大约为 min_hit_rate^number_of_stages。
-maxFalseAlarmRate
分类器的每一级允许最大FPR,默认0.5。总的为 max_false_alarm_rate^number_of_stages.
-weightTrimRate
样本权重按大小序累计超过此致的样本保留进入下一轮训练. 默认0.95。 见CvBoost::trim_weights
-maxDepth
弱分类器树最大的深度。默认是1,是二叉树(stumps),只使用一个特征。
-maxWeakCount
每一级中的弱分类器的最大数目。默认100
baseFormatSave 这个参数仅在使用Haar特征时有效。如果指定这个参数,那么级联分类器将以老的格式存储。
CvCascadeClassifier::train()概述了整个Cascade的执行过程。包括训练前的初始化,各Stage的强分类器间的样本集更新及强分类器训练都可看到其踪影,最显眼的还是其中的Stage训练的for大循环。
bool CvCascadeClassifier::train(...) { ... 读取正负样本 if ( !imgReader.create( _posFilename, _negFilename, _cascadeParams.winSize ) ) { cout << "Image reader can not be created from -vec " << _posFilename<< " and -bg " << _negFilename << "." << endl; return false; } 在指定data目录中读取已训练过的stagexml文件 if ( !load( dirName ) ) { 文件不存在则执行初始化过程, cascadeParams = _cascadeParams; 具体特征类型的创建与初始化 featureParams = CvFeatureParams::create(cascadeParams.featureType); featureParams->init(_featureParams); stageParams = new CvCascadeBoostParams; *stageParams = _stageParams; 还是采用main函数里面获取的命令行个参数取值 特征计算器 featureEvaluator = CvFeatureEvaluator::create(cascadeParams.featureType); 特征的初始化,里面生成了24*24正样本区域的162336个特征. featureEvaluator->init( (CvFeatureParams*)featureParams, numPos + numNeg, cascadeParams.winSize ); stageClassifiers.reserve( numStages ); } ...... 打印参数 <span style="color:#339999;">PARAMETERS: cascadeDirName: . vecFileName: trainingfaces_24-24.vec bgFileName: bg.txt numPos: 100 numNeg: 120 numStages: 20 precalcValBufSize[Mb] : 256 precalcIdxBufSize[Mb] : 256 stageType: BOOST featureType: HAAR 特征类型 sampleWidth: 24 sampleHeight: 24 boostType: GAB GENTLE AdaBoost minHitRate: 0.995 maxFalseAlarmRate: 0.5 weightTrimRate: 0.95 maxDepth: 1 只有一个分支节点的二叉决策树 maxWeakCount: 100 mode: BASIC</span> 已经从文件读取的训练过的stage int startNumStages = (int)stageClassifiers.size(); if ( startNumStages > 1 ) cout << endl << "Stages 0-" << startNumStages-1 << " are loaded" << endl; else if ( startNumStages == 1) cout << endl << "Stage 0 is loaded" << endl; double requiredLeafFARate = pow( (double) stageParams->maxFalseAlarm, (double) numStages ) / (double)stageParams->max_depth; 最终的虚警率 double tempLeafFARate; for( int i = startNumStages; i < numStages; i++ ) { cout << endl << "===== TRAINING " << i << "-stage =====" << endl; cout << "<BEGIN" << endl; 更新stage间的样本, 要做到训练新的stage的时候仍保障正负样本数足够. if ( !updateTrainingSet( tempLeafFARate ) ) { 样本数不够, 退出训练 cout << "Train dataset for temp stage can not be filled. Branch training terminated." << endl; break; } if( tempLeafFARate <= requiredLeafFARate ) { 虚警率已经达标 不再继续训练 cout << "Required leaf false alarm rate achieved. Branch training terminated." << endl; break; } CvCascadeBoost* tempStage = new CvCascadeBoost; cascade中一级的强分类器的训练过程 bool isStageTrained = tempStage->train( (CvFeatureEvaluator*)featureEvaluator, curNumSamples, _precalcValBufSize, _precalcIdxBufSize, *((CvCascadeBoostParams*)stageParams) ); cout << "END>" << endl; if(!isStageTrained) break; stageClassifiers.push_back( tempStage ); //保存阶段性的stage到独立xml文件 ............ } if(stageClassifiers.size() == 0) { cout << "Cascade classifier can't be trained. Check the used training parameters." << endl; return false; } 生成最终的xml文件 save( dirName + CC_CASCADE_FILENAME, baseFormatSave ); return true; }
在介绍AdaBoost的实现前本应该先介绍下CvCascadeClassifier::updateTrainingSet的, 但因为其中的fillPassedSamples用到了CvCascadeClassifier::predict, 所以这个我们还是后面再讲吧。
【2】AdaBoost的训练过程
AdaBoost由CvCascadeBoost类实现, 其继承自ml的CvBoost。
调用位置在CvCascadeClassifier::train中训练各Stage时调用
CvCascadeBoost* tempStage = new CvCascadeBoost; bool isStageTrained = tempStage->train( (CvFeatureEvaluator*)featureEvaluator, curNumSamples, _precalcValBufSize, _precalcIdxBufSize, *((CvCascadeBoostParams*)stageParams) );
参数含义
(CvFeatureEvaluator*)featureEvaluator, 特征提取器实现, HAAR LBP HOG
curNumSamples, 正负样本总数
_precalcValBufSize, _precalcIdxBufSize,前有说明,略
*((CvCascadeBoostParams*)stageParams) Boost实现的一些参数, 包括AdaBoost的类型GENTLE等, 前面已有说明了
在设计实现AdaBoost时最常用的弱分类器是决策树, 一般使用只含有一个节点的决策树就足够了,这就是所谓的stump(树桩).
算法描述中得到的强分类器有一系列改变权重的样本训练得到的弱分类器按一定系数的线性组合,涉及到我们现在分析的CvCascadeBoost实现便是由一系列CvCascadeBoostTree表示的弱分类器。
bool CvCascadeBoost::train(...) { ... 初始化Cascade中该级AdaBoost生成用到的训练数据。 此段比较耗时,后面分析 data = new CvCascadeBoostTrainData(...); weak = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvBoostTree*), storage ); //CvSeq* weak 多个弱分类器CvCascadeBoostTree的序列 初始化第一个弱分类器前的权值 update_weights( 0 ); do { 一个弱分类器及其训练过程 CvCascadeBoostTree* tree = new CvCascadeBoostTree; tree->train( data, subsample_mask, this ) 将训练好的弱分类器加入Seq中 cvSeqPush( weak, &tree ); 更新样本权值 update_weights( tree ); trim_weights(); if( cvCountNonZero(subsample_mask) == 0 ) break; } while( !isErrDesired() && (weak->total < params.weak_count) ); if(weak->total > 0) { data->is_classifier = true; data->free_train_data(); isTrained = true; } else clear(); return isTrained; }
其中的update_weights最开始参数为0时表示初始化权值为1.0/n
在训练完一个弱分类器后的update_weights(tree)则表示对权值的更新
void CvCascadeBoost::update_weights( CvBoostTree* tree )在权值更新流程时主要操作如下
<pre name="code" class="cpp">for( int i = 0; i < n; i++ ) weak_eval->data.db[i] *= -orig_response->data.i[i]; cvExp( weak_eval, weak_eval ); for( int i = 0; i < n; i++ ) { double w = weights->data.db[i] * weak_eval->data.db[i]; weights->data.db[i] = w; sumW += w; } // renormalize weights 权值归一化 if( sumW > FLT_EPSILON ) { sumW = 1./sumW; for( int i = 0; i < n; ++i ) weights->data.db[i] *= sumW; }
其中weak_eval表示弱分类器的系数, 但看实现是回归树,并不同于公式中的\alpha_k=0.5*ln((1-Ek)/Ek). 具体取值的计算还没搞明白.
上述代码第二个for循环及其之前描述的是newweight[i]=oldweight[i]*exp(-weak_eval[i]*orig_response[i])
最后的if是权值归一化过程,还是与文档描述很一致的.
相关推荐
在2015年的CVPR(计算机视觉与模式识别会议)上,OpenCV发布了重要的更新——OpenCV 3。这个版本带来了许多新功能和优化,提升了库的性能和易用性。 1. **模块化设计**:OpenCV 3引入了模块化设计,允许用户按需...
《WateRF:辐射场中的鲁棒水印技术在保护版权中的应用——基于Pytorch的实现》 在当今数字化时代,图像和视频内容的创作与传播日益广泛,版权保护问题显得尤为重要。WateRF(Watermarking in Radiation Fields for ...
该技术尤其关注在无监督的条件下,如何实现高质量的盲人脸修复,即在没有原始参考图像的情况下,恢复低质量或者损坏的人脸图像。"Python_Shell_下载.zip"表明此项目提供了用Python语言编写的源代码,可能还包含一个...
【CVPR2020-代码:CVPR 2020论文开放项目合集】是一个集合了2020年计算机视觉与模式识别大会(Computer Vision and Pattern Recognition, CVPR)上优秀论文的开源代码资源。这个压缩包旨在为研究者、开发者以及对...
这表明,压缩包内的代码可能与使用Darknet框架进行神经网络训练有关,可能是配置文件、权重文件、Python脚本或者C++源代码。 关于“文件转换”,这可能涉及多种情况。它可能是指将数据从一种格式转换成另一种,比如...
CVPR 2018笔记以下是我在大会期间遇到的最有趣的论文,挑战和研讨会的链接,注释和想法。 但是,您可能希望通过回顾所有979篇被接受的论文并逐步浏览所有21个教程和48个研讨会的内容,来形成自己对计算机视觉和模式...
有两个分支:与起始模板从相机只是显示帧和与工作示例。 按照此指南使用此示例创建自己的GitHub Page。 分叉此仓库(您需要拥有GitHub帐户) 转到“设置”,然后找到“ GitHub页面”部分。 选择master分支作为...
CVPR是由IEEE举办的国际计算机视觉与模式识别会议,是计算机视觉领域最重要的顶级会议之一,每年举办一次。该会议涵盖了计算机视觉领域的前沿研究和技术发展,包括图像处理、机器学习、深度学习等多个方向。CVPR不仅...
本文将详细介绍OpenSfM系统及其在计算机视觉领域中的应用,特别是作为2015年计算机视觉与模式识别大会(CVPR 2015)教程的一部分。OpenSfM是一个开源软件框架,专注于结构化从运动(Structure from Motion, SfM)...
标题中的“车道线检测 CVPR2022 PytorchAutoDrive: 源代码”表明这是一个关于车道线检测技术的研究项目,使用的工具是Pytorch框架,并且该项目在2022年的计算机视觉与模式识别会议(CVPR)上有所展示。CVPR是计算机...
RGBDTutorial-CVPR2014 是一个与计算机视觉领域相关的教程,源自于2014年计算机视觉与模式识别会议(CVPR)上的OpenCV教程。这个教程重点介绍了RGBD(红绿蓝深度)图像处理技术,通过Objective-C语言进行实现。RGBD...
SDFDiff已在python> = 3.7的Ubuntu 18.04上实现并测试。 克隆仓库: git clone https://github.com/YueJiang-nj/CVPR2020-SDFDiff.git 使用virtualenv或conda安装需求: # pip source virtual_env/install_pip....
CVPR2021-代码 论文开源项目(带代码的文件)合集!CVPR 2021论文收录列表: : 注1:等2021年2月28日开奖后,欢迎各位大佬提交issue,分享CVPR 2021本文和开源项目! 注2:CVPR 2021已交稿成立!已投稿且想要进来的...
- **更新内容**:相较于前一版本,主要增加了FREAK(Fast Retina Keypoint)特征描述符算法(CVPR 2012),该算法用于图像特征检测与描述,在计算机视觉领域具有重要意义。 - **文档结构**:文档分为多个章节,详细...
如我们的CVPR 2020出版物( )中所建议,该存储库包含用于对基于排名的深度度量学习方法运行策略适应性否定采样的代码。 SAMPLE_RUNS.sh中列出了可以达到与本文报告相似的结果的示例运行,因为基于RL的方法引入了更...
CVPR2020内存汇聚网络可实现高效的交互式视频对象分段这是CVPR2020论文“用于有效的交互式视频对象分段的内存聚合网络”的pytorch实施。准备依存关系Python 3.7 火炬1.0 脾气暴躁的张量板davisinteractive(请参阅)...
该代码是针对2017年计算机视觉与模式识别会议(CVPR)上发表的一种快速多帧立体声场景流算法的实现。在MATLAB环境中,它提供了一个用于处理和分析视频序列的开源系统。 【系统开源】标签意味着这些算法和代码是公开...
基于多视图CNN的3D手姿估计方法的实现。 Robust 3D Hand Pose Estimation in Single Depth Images: from Single-View CNN to Multi-View CNNs Liuhao Ge, Hui Liang, Junsong Yuan and Daniel Thalmann. Proceedings...
蔡氏电路matlab仿真代码这实现了“用于视觉关系检测的视觉翻译嵌入网络,张汉旺,邹林aw,张世富,蔡达成(CVPR2017)” 最近,yangxuntu还提供了张量流适应,这在vg数据集上获得了显着改进。 您可以在这里找到代码...
3 DaSiamRPN-ECCV2018:Distractor-aware Siamese Networks for Visual Object Tracking.pdf 4 SiamRPN++-CVPR2019:SiamRPN++: Evolution of Siamese Visual Tracking with Very Deep Networks.pdf 5 siamMask-CVPR...