均值滤波的快速解法

来源:互联网 发布:软件开发好学吗? 编辑:程序博客网 时间:2024/05/18 02:21

均值滤波的快速解法

均值滤波是一种非常常见的滤波方法,本身算法难度并不大,但是想当然的算法复杂度都是width*height*size的复杂度。下面我试着写了下一个height*width复杂度算法,当然算法并不是我原创,只不过我写了出来而已。

这个快速算法的精髓是采用一个数组代替滑动窗口。

下面以5*5的图像进行3*3的均值滤波为例。(height=width=5;size=3)

首先创建一个列和数组cur_rowSum,初始化为前size(3)行像素的列和。

0

5

7

9

0

(1)       列和数组为1*width

0

0

0

0

0

0

1

2

3

0

0

4

5

6

0

0

7

8

9

0

0

0

0

0

0

(2)       原始图像,周围pad为0

下面进行第一行的计算:

计算第一个像素的值,P=cur_rowSum[0..size-1],之后下一个像素的值刚好为p-最左一列的列和值加上最右一列的列和值。

 

0

5

7

9

0

 

0

0

0

0

0

0

12

2

3

0

0

4

5

6

0

0

7

8

9

0

0

0

0

0

0

由于在计算下一行的像素值时,也需要cur_rowSum。因此在第一行计算列和的时候同时计算下一个”cur_rowSum”,为了确保不影响本行的计算,因此采用另外一个数组存储。

计算时的方式为一个列和减去所在列的第一个像素,加上所在列的下一行像素。

0

12

7

9

0

 

0

0

0

0

0

0

1

2

3

0

0

4

5

6

0

0

7

8

9

0

0

0

0

0

0

如图,12=5-0+7;

如此进行循环进行,直到计算完毕,期间注意不要数组越界。

下面是代码。

#include<iostream>#include<vector>using namespace std;void avg_filter(int *src_pad,int height,int width,int size=3){int *src_pad1=src_pad;int *temp_src=src_pad1;vector<int> cur_sumRow(width,0);//初始化cur_sumRow为前size行元素的和,也就列和。for(int i=0;i<size;i++){for(int j=0;j<width;j++){cur_sumRow[j]+=*temp_src;//假设src为按行存储。temp_src++;}}/**假设src为pad后的矩阵,一般pad时,奇数扩展size-1行/列,偶数扩展size行*/int src_height=height-size/2*2;int src_width=width-size/2*2;//*生成原始图像大小的矩阵。int *result=new int[src_height*src_width];int *temp_pad=src_pad+size*width;int ind=0;//由于移动中需要更新列和数组的临时变量vector<int> temp_sumRow(width,0);for(int i=size/2;i<height-size/2;i++){int temp_sum=0;for(int cur_i=0;cur_i<width;cur_i++){temp_sumRow[cur_i]=cur_sumRow[cur_i];}for(int cur_i=0;cur_i<size;cur_i++){temp_sum+=temp_sumRow[cur_i];}for(int j=0;j<width;j++){if(j>=size/2&&j<width-size/2){result[ind]=temp_sum;ind++;//减去最左列的值,加上最右列的值。temp_sum-=temp_sumRow[j-size/2];if(j+size/2+1<width){if(size%2!=0){temp_sum+=temp_sumRow[j+size/2+1];}else{temp_sum+=temp_sumRow[j+size/2];}}}//减去最上一行的值,加上下一行的值。由于是一维存储,因此用两个指针快速访问cur_sumRow[j]-=*src_pad;src_pad++;//最后一行不计算。切会发生越界if(i!=height-size/2-1){cur_sumRow[j]+=*temp_pad;temp_pad++;}}//如果pad的为同一个数,不用考虑两端的列和变化、}for(int i=0;i<9;i++){cout<<result[i]<<" ";if((i+1)%3==0)cout<<endl;}}int main(){int src[25]={0, 0, 0, 0, 0,0, 1, 2, 3, 0,0, 4, 5, 6, 0,0, 7, 8, 9, 0,0, 0, 0, 0, 0};avg_filter(src,5,5,3);}


0 0
原创粉丝点击