盒式滤波器Box Filter

其主要功能是:在给定的滑动窗口大小下,对每个窗口内的像素值进行快速相加求和

在模式识别领域,Haar特征是大家非常熟悉的一种图像特征了,它可以应用于许多目标检测的算法中。与Haar相似,图像的局部矩形内像素的和、平方和、均值、方差等特征也可以用类似Haar特征的计算方法来计算。这些特征有时会频繁的在某些算法中使用,因此对它的优化势在必行。Boxfilter就是这样一种优化方法,它可以使复杂度为O(MN)的求和,求方差等运算降低到O(1)或近似于O(1)的复杂度,它的缺点是不支持多尺度。

盒式滤波器Box Filter

第一个提出Haar特征快速计算方法的是CVPR2001上的那篇经典论文Rapid Object Detection using a Boosted Cascade of Simple Features ,它提出了integral image的概念,这个方法使得图像的局部矩形求和运算的复杂度从O(MN)下降到了O(4)。它的原理很简单:首先建立一个数组A,宽高与原图像相等,然后对这个数组赋值,每个元素的值A[i]赋为该点与图像原点所构成的矩形中所有像素的和。初始化之后,想要计算某个矩形像素和的时候可以采用如下方法:如图D矩形的像素和就等于A[4] – A[2] – A[3] + A[1],共4次运算,即O(4)。Integral Image极大的提高了Haar特征的计算速度,它的优点在于能够快速计算任意大小的矩形求和运算。

  Boxfilter的原理有点类似Integral Image,而且比它还要快,但是实现步骤比较复杂。在计算矩形特征之前,Boxfilter与Integral Image都需要对图像进行初始化(即对数组A赋值),不同于Integral Image, Boxfilter的数组A中的每个元素的值是该像素邻域内的像素和(或像素平方和),在需要求某个矩形内像素和的时候,直接访问数组中对应的位置就可以了。因此可以看出它的复杂度是O(1)。

 

盒式滤波器Box Filter

Boxfilter的初始化过程如下:

1、给定一张图像,宽高为(M,N),确定待求矩形模板的宽高(m,n),如图紫色矩形。图中每个黑色方块代表一个像素,红色方块是假想像素。

2、开辟一段大小为M的数组,记为buff, 用来存储计算过程的中间变量,用红色方块表示

3、将矩形模板(紫色)从左上角(0,0)开始,逐像素向右滑动,到达行末时,矩形移动到下一行的开头(0,1),如此反复,每移动到一个新位置时,计算矩形内的像素和,保存在数组A中。以(0,0)位置为例进行说明:首先将绿色矩形内的每一列像素求和,结果放在buff内(红色方块),再对蓝色矩形内的像素求和,结果即为紫色特征矩形内的像素和,把它存放到数组A中,如此便完成了第一次求和运算。

4、每次紫色矩形向右移动时,实际上就是求对应的蓝色矩形的像素和,此时只要把上一次的求和结果减去蓝色矩形内的第一个红色块,再加上它右面的一个红色块,就是当前位置的和了,用公式表示 sum[i] = sum[i-1] - buff[x-1] + buff[x+m-1]

5、当紫色矩形移动到行末时,需要对buff进行更新。因为整个绿色矩形下移了一个像素,所以对于每个buff[i], 需要加上一个新进来的像素,再减去一个出去的像素,然后便开始新的一行的计算了。

 

  Boxfilter的初始化过程非常快速,每个矩形的计算基本上只需要一加一减两次运算。从初始化的计算速度上来说,Boxfilter比Integral Image要快一些,大约25%。在具体求某个矩形特征时,Boxfilter比Integral Image快4倍,所谓的4倍其实就是从4次加减运算降低到1次,虽然这个优化非常渺小,但是把它放到几层大循环里面,还是能节省一些时间的。对于那些实时跟踪检测算法,一帧的处理时间要严格在40ms以下,正是这些细小的优化决定了程序的效率,积少成多,聚沙成塔。

下面的程序是Boxfilter的示例代码,谨供参考(C语言)

 1 #include <stdio.h>

 2 #include <stdlib.h>

 3 #include <math.h>

 4 #include <opencv2\opencv.hpp>  

 5 

 6 void displayImageNewWindow(char *title,CvArr* img){

 7     cvNamedWindow(title,1);

 8     cvShowImage(title,img);

 9 }

10 void box_filter(IplImage* img,IplImage* result){

11     //init part

12     CvScalar s;

13     int width = img->width, height = img->height;

14     int m_w = 5,m_h = 5;//window_size

15     int boxwidth = width - m_w, boxheight = height - m_h;

16     int *sum = (int*)malloc(boxwidth *boxheight*sizeof(double));

17     int *buff= (int*)malloc(width*sizeof(double));

18     memset(sum,0,boxwidth *boxheight*sizeof(int));

19     memset(buff,0,width*sizeof(int));

20     

21     //set buff:from 0 to 4 rows,per col

22     int x,y,j;

23     for(y=0; y<m_h; y++){

24         for(x=0; x<width; x++){

25             uchar pixel = CV_IMAGE_ELEM(img,uchar,y,x);

26             buff[x] += pixel;

27             //printf("%d:%d\n",x,buff[x]);

28         }    

29     }

30 

31     for(y=0; y<height - m_h;y++){

32         int Xsum = 0;

33 

34         for(j=0; j<m_w; j++){

35             Xsum += buff[j];//sum of pixel from (0,0) to (m_h,m_w) (also x = 0)

36         }

37 

38         for(x=0; x<boxwidth; x++){

39             if(x!=0){

40                 Xsum = Xsum-buff[x-1]+buff[m_w-1+x];//Xsum:sum of cols range from x to x+m_w ,rows range from 0 to 4

41             }

42             sum[y*boxwidth + x] = (float) Xsum;        

43         }

44 

45         for(x=0; x<width; x++){

46             uchar pixel = CV_IMAGE_ELEM(img,uchar,y,x);//img[y *width + x];    

47             uchar pixel2= CV_IMAGE_ELEM(img,uchar,y+m_h,x);//img[(y+mheight) *width + x];    

48             buff[x] = buff[x] - pixel + pixel2;      

49         }

50     }

51     //遍历,得到每个点的和,传给矩阵result

52     for( y=0; y<height-5; y++){

53         for( x=0; x<width; x++){

54             if(y>m_h/2 && y<height - m_h/2 && x>m_w/2 && x<width - m_w/2){

55                 s.val[0] =  sum[(y - m_h/2) *boxwidth + (x - m_h/2)]/(m_h*m_w);

56                 cvSet2D(result,y,x,s);

57             }else{

58                 s.val[0] = -1;

59                 cvSet2D(result,y,x,s);

60             }//end else

61         }//end the first for

62     }//end the second for

63 }

64 int main(int argc,char** argv){

65     IplImage* left = cvLoadImage(argv[1]);

66     IplImage* dst = cvCreateImage(cvGetSize(left),8,1);

67     IplImage* mat =  cvCreateImage(cvGetSize(left),8,1);

68     cvZero(mat);

69     cvCvtColor(left,dst,CV_RGB2GRAY);

70     box_filter(dst,mat);

71     displayImageNewWindow("mat",mat);

72     cvWaitKey();

73     return 0;

74 }

 

你可能感兴趣的:(filter)