热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

OpenCV中的Haar+Adaboost级联分类器分解(二):级联分类器结构与XML文件含义

众所周知,OpenCV中的Adaboost级联分类是树状结构,如图1,其中每一个stage都代表一级强分类器。当检测窗口通过所有的强分类器
众所周知,OpenCV中的Adaboost级联分类是树状结构,如图1,其中每一个stage都代表一级强分类器。当检测窗口通过所有的强分类器时才被认为是目标,否则拒绝。实际上,不仅强分类器是树状结构,强分类器中的每一个弱分类器也是树状结构。

 

图1 强分类器和弱分类器示意图

 

    这篇文章将结合OpenCV-2.4.11中自带的haarcascade_frontalface_alt2.xml文件介绍整个级联分类器的结构。需要说明,自从2.4.11版本后所有存储得XML分类器都被替换成新式XML,所以本文对应介绍新式分类器结构。

(一)XML的头部

    在了解OpenCV分类器结构之前,先来看看存储分类器的XML文件中有什么。图2中注释了分类器XML文件头部信息,括号中的参数为opencv_traincascade.exe训练程序对应参数,即训练时设置了多少生成的XML文件对应值就是多少(如果不明白,可以参考我的前一篇文章)。

 

图2 分类器XML文件头部含义

(二)弱分类器结构

 

    之前看到有一部分文章将Haar特征和弱分类器的关系没有说清楚,甚至有些还把二者弄混了。其实Haar特征和弱分类器之间的关系很简单:

一个完整的弱分类器包含:Haar特征

+leftValue + rightValue + 弱分类器阈值(threshold)

这些元素共同构成了弱分类器,缺一不可。haarcascade_frontalface_alt2.xml的弱分类器深度为2,包含了2种形式,如图3。图3中的左边形式包含2个Haar特征、1个leftValue、2个rightValue和2个弱分类器阈(t1和t2);左边形式包括2个Haar特征、2个leftValue、1个rightValue和2个弱分类器阈。

 

图3 OpenCV树状弱分类器示意图

    看图3应该明白了弱分类器的大致结构,接下来我们了解树状弱分类器是如何工作的。还是以图3左边的形式为例:

 

    1.计算第一个Haar特征的特征值haar1,与第一个弱分类器阈值t1对比,当haar1t1时,该弱分类器输出rightValue2并结束。   

 

    2.计算第二个Haar特征值haar2,与第二个弱分类器阈值t2对比,当haar2t2时输出rightValue1。   

 

    即通过上述步骤计算弱分类器输出值,这与OpenCV的cascadedetect.hpp文件中的predictOrdered()函数代码对应(这里简单解释一下,在OpenCV中所有弱分类器的leftValue和rightValue都依次存储在一个一维数组中,代码中的leafOfs表示当前弱分类器中leftValue和rightValue在该数组中存储位置的偏移量,idx表示在偏移量leafOfs基础上的leftValue和rightValue值的索引,cascadeLeaves[leafOfs

-idx]就是该弱分类器的输出):

[cpp] view plaincopy
  1. do  
  2.             {  
  3.                CascadeClassifier::Data::DTreeNode& node = cascadeNodes[root + idx];  
  4.                 double val =featureEvaluator(node.featureIdx);  
  5.                 idx &#61; val < node.threshold ?node.left : node.right;  
  6.             }  
  7.             while( idx > 0 );  
  8.             sum &#43;&#61; cascadeLeaves[leafOfs -idx];  





 

    看到这里&#xff0c;你应该明白了弱分类器的工作方式&#xff0c;即通过计算出的Haar特征值与弱分类器阈值对比&#xff0c;从而选择最终输出leftValue和rightValue值中的哪一个。   

        那么第三个问题来了&#xff0c;这些Haar特征、leftValue、rightValue和弱分类器阈值t都是如何存储在xml文件中的&#xff1f;不妨来看haarcascade_frontalface_alt2.xml文件中的第一级的第三个弱分类器&#xff0c;如图4。图4中的弱分类器恰好是图3中左边类型&#xff0c;包含了两个标签。其中标签中的3个浮点数由左向右依次是rightValue2、leftValue和rightValue1&#xff08;具体顺序参考下文图示&#xff09;&#xff1b;而中有6个整数和2个浮点数&#xff0c;其中2个浮点数依次分别是弱分类器阈值t1和t2&#xff0c;剩下的6个整数容我慢慢分解。   

        首先来看两个浮点数前的整数&#xff0c;即4和5。这两个整数用于标示所属本弱分类器Haar特征存储在标签中的位置。比如数值4表示该弱分类器的haar1特征存储在xml文件下面标签中第4个位置&#xff0c;即为&#xff1a;   

    &#xff08;标签里面的5个数对应Haar特征的&#xff0c;请参考上一篇文章&#xff09;。的其他4个整数1、0、-1和-2则用于控制弱分类器树的形状&#xff0c;即OpenCV会把1赋值给当前的node.left&#xff0c;并把0赋值给node.right。请注意do-while代码中的条件&#xff0c;只有idx<&#61;0时才停止循环&#xff0c;参考图3应该可以理解这4个整数的含义。如此&#xff0c;OpenCV通过这些巧妙的数值和结构&#xff0c;控制了整个分类器的运行&#xff08;当然我举的例子alt2的弱分类器树深度为2&#xff0c;相对比较复杂&#xff0c;其他如alt等深度为1的分类器则更加简单&#xff09;。其他弱分类器请类推。   

 

图4 OpenCV弱分类器运行示意图

 

        可以看到&#xff0c;每个弱分类器内部都是类似于这种树状的“串联”结构&#xff0c;所以我称其为“串联组成的的弱分类器”。&#xff08;需要说明&#xff0c;本文为了介绍原理&#xff0c;选用了深度为2的分类器。而深度为1的分类器&#xff0c;如haarcascade_frontalface_alt.xml&#xff0c;则相比较简单&#xff0c;可以通过类比了解&#xff0c;不再赘述&#xff09;&#xfeff;&#xfeff;   

&#xff08;三&#xff09;强分类器结构

    在OpenCV中&#xff0c;强分类器是由多个弱分类器“并列”构成&#xff0c;即强分类器中的弱分类器是两两相互独立的。在检测目标时&#xff0c;每个弱分类器独立运行并输出cascadeLeaves[leafOfs

-idx]值&#xff0c;然后把当前强分类器中每一个弱分类器的输出值相加&#xff0c;即&#xff1a;

sum&#43;&#61; cascadeLeaves[leafOfs - idx];&#xfeff;&#xfeff;

 

图5 OpenCV强分类器运行示意图

之后与本级强分类器的stageThreshold阈值对比&#xff0c;当且仅当结果sum>stageThreshold时&#xff0c;认为当前检测窗口通过了该级强分类器。当前检测窗口通过所有强分类器时&#xff0c;才被认为是一个检测目标。

    可以看出&#xff0c;强分类器与弱分类器结构不同&#xff0c;是一种类似于“并联”的结构&#xff0c;我称其为“并联组成的强分类器”。

&#xff08;四&#xff09;级联分类器

    通过之前的介绍&#xff0c;到这应该可以理解OpenCV中&#xff1a;由弱分类器“并联”组成强分类器&#xff0c;而由强分类器“串联”组成级联分类器。那么还剩最后一个内容&#xff0c;那就是检测窗口大小固定&#xff08;例如alt2是20*20像素&#xff09;的级联分类器如何遍历图像&#xff0c;以便找到在图像中大小不同、位置不同的目标。

1. 为了找到图像中不同位置的目标&#xff0c;需要逐次移动检测窗口&#xff08;随着检测窗口的移动&#xff0c;窗口中的Haar特征相应也随着窗口移动&#xff09;&#xff0c;这样就可以遍历到图像中的每一个位置&#xff1b;

2. 而为了检测到不同大小的目标&#xff0c;一般有两种做法&#xff1a;逐步缩小图像or逐步放大检测窗口。缩小图像就是把图像长宽同时按照一定比例&#xff08;默认1.1 or 1.2&#xff09;逐步缩小&#xff0c;然后检测&#xff1b;放大检测窗口是把检测窗口长宽按照一定比例逐步放大&#xff0c;这时位于检测窗口内的Haar特征也会对应放大&#xff0c;然后检测。一般来说&#xff0c;如果用软件实现算法&#xff0c;则放大检测窗口相比运行速度更快。


推荐阅读
  • 本文介绍了使用哈夫曼树实现文件压缩和解压的方法。首先对数据结构课程设计中的代码进行了分析,包括使用时间调用、常量定义和统计文件中各个字符时相关的结构体。然后讨论了哈夫曼树的实现原理和算法。最后介绍了文件压缩和解压的具体步骤,包括字符统计、构建哈夫曼树、生成编码表、编码和解码过程。通过实例演示了文件压缩和解压的效果。本文的内容对于理解哈夫曼树的实现原理和应用具有一定的参考价值。 ... [详细]
  • 本文介绍了使用kotlin实现动画效果的方法,包括上下移动、放大缩小、旋转等功能。通过代码示例演示了如何使用ObjectAnimator和AnimatorSet来实现动画效果,并提供了实现抖动效果的代码。同时还介绍了如何使用translationY和translationX来实现上下和左右移动的效果。最后还提供了一个anim_small.xml文件的代码示例,可以用来实现放大缩小的效果。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文讲述了如何通过代码在Android中更改Recycler视图项的背景颜色。通过在onBindViewHolder方法中设置条件判断,可以实现根据条件改变背景颜色的效果。同时,还介绍了如何修改底部边框颜色以及提供了RecyclerView Fragment layout.xml和项目布局文件的示例代码。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 本文介绍了在Vue项目中如何结合Element UI解决连续上传多张图片及图片编辑的问题。作者强调了在编码前要明确需求和所需要的结果,并详细描述了自己的代码实现过程。 ... [详细]
  • Android系统移植与调试之如何修改Android设备状态条上音量加减键在横竖屏切换的时候的显示于隐藏
    本文介绍了如何修改Android设备状态条上音量加减键在横竖屏切换时的显示与隐藏。通过修改系统文件system_bar.xml实现了该功能,并分享了解决思路和经验。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • Go语言实现堆排序的详细教程
    本文主要介绍了Go语言实现堆排序的详细教程,包括大根堆的定义和完全二叉树的概念。通过图解和算法描述,详细介绍了堆排序的实现过程。堆排序是一种效率很高的排序算法,时间复杂度为O(nlgn)。阅读本文大约需要15分钟。 ... [详细]
  • Day2列表、字典、集合操作详解
    本文详细介绍了列表、字典、集合的操作方法,包括定义列表、访问列表元素、字符串操作、字典操作、集合操作、文件操作、字符编码与转码等内容。内容详实,适合初学者参考。 ... [详细]
  • 突破MIUI14限制,自定义胶囊图标、大图标样式,支持任意APP
    本文介绍了如何突破MIUI14的限制,实现自定义胶囊图标和大图标样式,并支持任意APP。需要一定的动手能力和主题设计师账号权限或者会主题pojie。详细步骤包括应用包名获取、素材制作和封包获取等。 ... [详细]
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
  • Learning to Paint with Model-based Deep Reinforcement Learning
    本文介绍了一种基于模型的深度强化学习方法,通过结合神经渲染器,教机器像人类画家一样进行绘画。该方法能够生成笔画的坐标点、半径、透明度、颜色值等,以生成类似于给定目标图像的绘画。文章还讨论了该方法面临的挑战,包括绘制纹理丰富的图像等。通过对比实验的结果,作者证明了基于模型的深度强化学习方法相对于基于模型的DDPG和模型无关的DDPG方法的优势。该研究对于深度强化学习在绘画领域的应用具有重要意义。 ... [详细]
author-avatar
小情人恩恩baby
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有