Haar特征理解

作者和出处:http://blog.csdn.net/xiaowei_cqu


最早的Haar特征由Papageorgiou C.等提出(《A general framework for object detection》),后来Paul Viola和Michal Jones提出利用积分图像法快速计算Haar特征的方法(《Rapid object detection using a boosted cascade of simple features》)。之后,Rainer Lienhart 和 Jochen Maydt用对角特征对Haar特征库进行了扩展(《An extended set of Haar-like features for rapid object detection》)。OpenCV的Haar分类器就是基于扩展后的特征库实现的。


Haar特征/矩形特征

Haar特征本身并不复杂,就是用图中黑色矩形所有像素值的和减去白色矩形所有像素值的和。

Haar特征理解_第1张图片

看过Rainer Lienhart文章的人知道,Rainer Lienhart在文章中给出了计算特定图像面积内Haar特征个数公式。到最后也没推出那个公式来,还望看明白的大牛留言指教~


Haar特征个数计算

 

Rainer Lienhart计算Haar特征个数的公式:


其中,为图片大小,为矩形特征大小,表示矩形特征在水平和垂直方向的能放大的最大比例系数。

对于45°的rotated特征(如1(c)和1(d)),w,h表示如下图所示:

Haar特征理解_第2张图片

其计算公式为:


*论文中没有说明,个人认为此处除了Z,XY值也有变化:


下面是我理解的计算过程~

首先有两点要清楚:

1、对于某特定大小的特征,在窗口内滑动计算。
      也就是如图1(a)特征大小为2*1,对于24*24的图像。水平可滑动23步,垂直滑动24步,所以共有23*24个特征。

2、对于一个特征,特征本身沿水平、竖直方向分别缩放。
      还看特征1(a),特征大小为2*1,则延水平方向可放大为:4*1,6*1,8*1,…,24*1;竖直方向可放大为:2*1,2*2,2*3,…,2*24。即每个特征有XY种放大方式。(!放大的矩形特征并限制保持2:1的比例!)


清楚这两点,就很容易写出计算特征个数的代码:

[cpp]  view plain  copy
  1. int getHaarCount(int W,int H,int w,int h){  
  2.     int X=W/w;  
  3.     int Y=H/h;  
  4.     int count=0;  
  5.   
  6.     //放大Haar特征到 iw*jh  
  7.     for (int i=1;i<=X;i++)  
  8.         for(int j=1;j<=Y;j++)  
  9.             //滑动iw*jh矩形,遍历图像计算每个位置Haar特征  
  10.             for(int x=1;x<=W-i*w+1;x++)  
  11.                 for(int y=1;y<=H-j*h+1;y++)  
  12.                     count++;  
  13.   
  14.     return count;  
  15. }  


对于45°特征,由于Rainer Lienhart定义的w,h与原矩阵含义不同(参见第一幅图),即实际滑动的矩阵框为(h+w)*(w+h)。

所以只要用如下方式调用原函数:

[cpp]  view plain  copy
  1. getHaarCount(W,H,h+w,w+h);  

当然如果你喜欢写代码,也可以写个新的函数:

[cpp]  view plain  copy
  1. int getRotatedHaarCount(int W,int H,int w,int h){  
  2.     int X=W/(w+h);//计算新的X  
  3.     int Y=H/(w+h);//计算新的Y  
  4.     int count=0;  
  5.     for (int i=1;i<=X;i++)  
  6.         for(int j=1;j<=Y;j++)  
  7.             //注意这里滑动窗口边界变化  
  8.             for(int x=1;x<=W-i*(w+h)+1;x++)  
  9.                 for(int y=1;y<=H-j*(w+h)+1;y++)  
  10.                     count++;  
  11.   
  12.     return count;  
  13. }  


计算在24*24的图片中,几种特征的个数为:

Haar特征理解_第3张图片


可以看到和论文用公式计算得到的值是一致的~

Haar特征理解_第4张图片


另一种递推计算方法:

特征个数虽然很大,但很有规律,不用程序用笔也很容易推出递推公式。

如1(a)和1(b)特征递推为:(12^2)*(1+2+...+24)=43,200

具体参见此贴:Re: [OpenCV] Re: Number of haar features


Haar-like特征的计算积分图

       积分图就是只遍历一次图像就可以求出图像中所有区域像素和的快速算法,大大的提高了图像特征值计算的效率。

       积分图主要的思想是将图像从起点开始到各个点所形成的矩形区域像素之和作为一个数组的元素保存在内存中,当要计算某个区域的像素和时可以直接索引数组的元素,不用重新计算这个区域的像素和,从而加快了计算(这有个相应的称呼,叫做动态规划算法)。积分图能够在多种尺度下,使用相同的时间(常数时间)来计算不同的特征,因此大大提高了检测速度。

       我们来看看它是怎么做到的。

       积分图是一种能够描述全局信息的矩阵表示方法。积分图的构造方式是位置(i,j)处的值ii(i,j)是原图像(i,j)左上角方向所有像素的和:

  

Haar特征理解_第5张图片        

积分图构建算法:

1)用s(i,j)表示行方向的累加和,初始化s(i,-1)=0;

2)用ii(i,j)表示一个积分图像,初始化ii(-1,i)=0

3)逐行扫描图像,递归计算每个像素(i,j)行方向的累加和s(i,j)和积分图像ii(i,j)的值

s(i,j)=s(i,j-1)+f(i,j)

ii(i,j)=ii(i-1,j)+s(i,j)

4)扫描图像一遍,当到达图像右下角像素时,积分图像ii就构造好了。

积分图构造好之后,图像中任何矩阵区域的像素累加和都可以通过简单运算得到如图所示。

Haar特征理解_第6张图片          

D的四个顶点分别为α、β、γ、δ,则D的像素和可以表示为

Dsum = ii( α )+ii( β)-(ii( γ)+ii( δ ));

        而Haar-like特征值无非就是两个矩阵像素和的差,同样可以在常数时间内完成。所以矩形特征的特征值计算,只与此特征矩形的端点的积分图有关,所以不管此特征矩形的尺度变换如何,特征值的计算所消耗的时间都是常量。这样只要遍历图像一次,就可以求得所有子窗口的特征值。


你可能感兴趣的:(Haar特征理解)