zoukankan      html  css  js  c++  java
  • 对OpenCV中Haar特征CvHaarClassifierCascade等结构理解

    首先说一下这个级联分类器,OpenCV中级联分类器是根据VJ 04年的那篇论文(Robust Real-Time Face Detection)编写的,查看那篇论文,知道构建分类器的步骤如下:

    1、根据haar-like特征训练多个弱分类器

    2、使用adaboost算法将多个弱分类器组合成一个强分类器

    3、最终的分类器是由多个强分类器级联而成

    下面这幅图是弱分类器组合成强分类器的示意图(图片来源于网络):

    下面这张是多个强分类器级联的示意图(图片来源于网络):

    在了解了级联分类器是怎么一回事后,我们来看一看OpenCV里面级联分类器的结构

    在调用OpenCV中的级联分类器对目标进行分类时,都会将一个训练好的分类器(一个训练好的.xml文件)读入到一个CvHaarClassifierCascade结构中,如下:

     1 CvHaarClassifierCascade* cascade = (CvHaarClassifierCascade*)cvLoad( "haarcascade_frontalface_alt.xml", 0, 0, 0 );  

    那么这个CvHaarClassifierCascade结构体里面的内容都有哪些呢?

     1 typedef struct CvHaarClassifierCascade
     2 {
     3     int  flags;                 /* 标志位 */
     4     int  count;                 /* 分级分类器中强分类器的数量 */
     5     CvSize orig_window_size;     /* 训练中原始目标的大小 */ 
     6     
     7     /* these two parameters are set by cvSetImagesForHaarClassifierCascade */
     8     CvSize real_window_size;     /* 待检测物体的大小 */
     9     double scale;                /* Haar块缩放的尺寸 */
    10     
    11     CvHaarStageClassifier* stage_classifier; /* 定义强分类器数组 */ 
    12     CvHidHaarClassifierCascade* hid_cascade;
    13 }CvHaarClassifierCascade;

    第一个flags,还不是很清楚,在debug模式下,flags=1112539136(好吧,这个值很诡异),我也不是很清楚

    第二个count,表示整个分级分类器中强分类器的数量,即最后参与级联的强分类器的个数

    第三个orig_window_size,表示的是在训练时用的正样本的尺寸,OpenCV中的尺寸是20x20

    第四个和第五个,注释中说了,这两个参数需要自己设置,具体每个参数看注释

    第六个stage_classifier,是强分类器指针,指向一个强分类器数组,之前的count是多少,那么此处的强分类器就有多少

    最后一个hid_cascade,还不是很清楚

    下面来看上面第六个参数的强分类器结构体

     1 typedef struct CvHaarStageClassifier
     2 {
     3     int  count;  /* number of classifiers in the battery 构成强分类器的弱分类器的数量*/
     4     float threshold; /* threshold for the boosted classifier 叠加分类器的阈值*/
     5     CvHaarClassifier* classifier; /* array of classifiers 定义分类器数组*/
     6     /* these fields are used for organizing trees of stage classifiers,
     7        rather than just stright cascades */
     8     int next;
     9     int child;
    10     int parent;
    11 }CvHaarStageClassifier;

    第一个count,表示该强分类器中,弱分类器的数量,即该强分类器由多少个弱分类器组成

    第二个threshold,叠加分类器的阈值(好吧。。这个我也不知道)

    第三个classifier,是一个指针,指向的是一个弱分类器数组,之前的count是多少,此处的弱分类器就有多少

    后面3个都不清楚。。。(望知道的网友给予帮助)

    下面是弱分类器的结构

     1 typedef struct CvHaarClassifier
     2 {
     3     int count;      /* number of nodes in the decision tree */
     4     /* these are "parallel" arrays. Every index i corresponds to a node of the decision tree (root has 0-th index).
     5     left[i] - index of the left child (or negated index if the left child is a leaf)
     6     right[i] - index of the right child (or negated index if the right child is a leaf)
     7     threshold[i] - branch threshold. if feature responce is <= threshold, left branch is chosen, otherwise right branch is chosed.
     8     alpha[i] - output value correponding to the leaf. */
     9 
    10     CvHaarFeature* haar_feature;
    11     float* threshold;
    12     int* left;
    13     int* right;
    14     float* alpha;
    15 }CvHaarClassifier;

    第一个count,在opencv里,发现始终都是1,自己想了想,因为这个结构体记录的是一个弱分类器,自然弱分类器的个数就是1了。

    第二个haar_feature,也是一个指针,指向一个(因为count是1)特征结构体CvHaarFeature,这个结构体中记录的内容是弱分类器的类型(包括该haar-like特征的位置,大小,以及种类,这个结构体会在下面给出,再细说)

    第三个threshold,就是那个判别函数:h(x,f,p,theta) = (p*f(x) < p*theta ? 1 : 0),中的阈值theta

       

    第四个left,第五个right不是很清楚(求知道的同学详解啊~~~~)

    第六个alpha,就是这个弱分类器的权重(每一个强分类器都是由多个弱分类器按照各自的权重进行表决,而得到的)

    特征的结构体如下

     1 #define CV_HAAR_FEATURE_MAX  3
     2 // 一个Haar特征由2~3个具有相应权重的矩形组成
     3 typedef struct CvHaarFeature
     4 {
     5     int  tilted;      // 0 means up-right feature, 1 means 45-rotated feature
     6     struct
     7     {
     8         CvRect r;
     9         float weight;
    10     } rect[CV_HAAR_FEATURE_MAX]; 
    11     // 2-3 rectangles with weights of opposite signs and with absolute values inversely proportional to the areas of the rectangles. if rect[2].weight != 0, then the feature     consists of 3 rectangles, otherwise it consists of 2.
    12 }CvHaarFeature;

    第一个参数titled,0表示该特征是标准的haar-like特征,1表示旋转45°后的特征

      标准的haar-like特征如下:

          

      而旋转45°后的特征如下:

          

    第二个参数是个结构体数组,每个结构体中包括一个矩形和一个权重,这个数组的大小是CV_HAAR_FEATURE_MAX(3)(注释中说:此处可能有2~3个矩形,这里的矩形等看了下面的解释就知道了),这个矩形和权重有什么用呢?

      在debug模式下,查看第一个弱分类器数组内的元素

      第一个元素:

    1 rect[0].r.x = 3
    2 rect[0].r.y = 7
    3 rect[0].r.width = 14
    4 rect[0].r.height = 4
    5 rect[0].weight = -1

      第二个元素:

    1 rect[1].r.x = 3
    2 rect[1].r.y = 9
    3 rect[1].r.width = 14
    4 rect[1].r.height = 2
    5 rect[1].weight = 2

      第三个元素则全都是0

      这么看这些坐标,并不是很清楚,我们可以画个图:

      

      由图可见,第一个矩形表示的是A+B区域,第二个矩形表示的是B区域。

      此时再看一看每个元素的权重weight,结合积分图的概念,发现第一个矩形的积分图乘以其权重加上第二个积分图乘以其权重,恰好得到下述结果:

      (A+B)*(-1)+B*2=B-A

      看到这个公式,大家都不会陌生,这正式VJ论文中给出的众多haar-like模板中的其中一个模板的计算方法(此处不知如何表达,大家将就,看懂就行) 

    我们继续考察第二个弱分类器的特征部分,其特征参数如下:

    1 rect[0].r.x = 1, rect[0].r.y = 2
    2 rect[0].r.width = 18, rect[0].r.height = 4
    3 rect[0].weight = -1
    4 
    5 rect[1].r.x = 7, rect[1].r.y = 2
    6 rect[1].r.width = 6, rect[1].r.height = 4
    7 rect[1].weight = 3

    数组的第三个元素依然都是是0,对其绘图:

      

      第一块矩形区域是A+B+C,第二块矩形区域是B,积分图乘以权重,再相加,可得:

      (A+B+C)*(-1)+B*3 = 2*B-A-C

      也是haar-like特征模板之一(此处不知如何表达,大家将就,看懂就行)

    刚刚找了好久,找到一个第三个元素权重不为0的,该数组三个元素如下:

     1 rect[0].r.x = 0, rect[0].r.y = 2
     2 rect[0].r.width = 20, rect[0].r.height = 6;
     3 rect[0].weight = -1
     4 
     5 rect[1].r.x = 10, rect[1].r.y = 2
     6 rect[1].r.width = 10, rect[1].r.height = 3;
     7 rect[1].weight = 2
     8 
     9 rect[2].r.x = 0, rect[2].r.y = 5
    10 rect[2].r.width = 10, rect[2].r.height = 3;
    11 rect[2].weight = 2

     绘图可得:

      

      将每个矩形乘以相应的权重,相加可得:

      (A+B+C+D)*(-1)+2*B + 2*C = B+C-(A+D)

      也是模板之一

      (佩服设计这个结构体的程序员)

    到此,四个结构体都说完了,如有不对,请大家指正

  • 相关阅读:
    04、Unity_声音管理器
    StreamingAssets文件夹的读取异常
    Unity做360度的全景照片
    07.C#中如何排除/过滤/清空/删除掉字符串数组中的空字符串
    03、三种简单的计时器
    02、在层级未知情况下通过递归查找子物体
    Java中请优先使用try-with-resources而非try-finally
    Redis——入门学习笔记
    KafKa——学习笔记
    SpringBoot——学习笔记
  • 原文地址:https://www.cnblogs.com/pakfahome/p/3611303.html
Copyright © 2011-2022 走看看