快捷搜索:

图像处理之快速均值模糊(Box Blur)

注:本文内容来自于网络转载

转自:http://blog.csdn.net/real_myth/article/details/49273607

图像模糊的本质, 从数字信号处理的角度看,图像模糊就要压制高频信号保留低频信号,

压制高频的信号的一个可选择的方法就是卷积滤波。选择一个低频滤波器,对图像上的

每个像素实现低频滤波,这样整体效果就是一张数字图像更加的模糊,显示更少的细节信息。

 传统的卷积模糊计算量巨大,程序效率比较低,基于滑动窗口的Box Blur是一种快速模糊方法,

其结果近似于卷积模糊的结果。我没证明过!

 

一:Box Blur数学原理

根据输入的半径R,计算起始2*R +1个像素的平均值, 作为第一个输出像素的结果,

公式可以表示为

像素 X0 =  其中K代表输入像素集合, i的取值范围为 i∈[-R, R]

然后计算每一行输出像素的值根据Xi = X0 + (K[index + R + 1] – K[index - R])

 

二:Box Blur的特征

Box Blur是一种快速的图像模糊技术, 相比于传统的卷积模糊,Box Blur可以更有效率的

完成对图像模糊, 模糊的程度取决一下三个输入参数,

1.      X方向上半径 H Radius

2.      Y方向上半径 V Radius

3.      迭代次数 Iteration number

在半径相同的情况下, 迭代次数越多,输出的图像就越模糊

在迭代次数相同的情况下, 像素半径越大, 输出的图像就越模糊

上述两者之间的不同是对图像的拉伸效果, 半径越大,对图像的拉伸效果越显著

 

Box模糊利用滑动窗口算法,从而简化了每次计算平均值带来额外开销。

 

从数字图像和信号处理的角度看, Box Blur是一种不折不扣的低通滤波, 但是它并不

是真正的高斯低通滤波, 不是卷积实现, 因而速度更快。

 当水平和垂直半径分别为1 时,是典型的3*3 的矩阵卷积

1, 1, 1

1, 1, 1

1, 1, 1

计算, 相比于传统的卷积计算之后,要进行归一化处理,box计算过程中已经完成像素平均,

无需归一化处理。


三:基于滑动窗口算法的Box模糊效果

 

水平和垂直方向

 

垂直方向:

 

 

水平方向:

 

四:程序关键代码解析

注释已经很详细的写在代码中,最重要的一个步骤是提前建立index,根据index来找到平均值。

 

[java] view plaincopy
  1. "font-weight: normal;"   public static void blur( int[] in, int[] out, int width, int height, int radius  
  2.         int widthMinus1 width-1 
  3.         int tableSize 2*radius+1 
  4.         int divide[] new int[256*tableSize];  
  5.   
  6.         // the value scope will be to 255, and number of is table size  
  7.         // will get means from index not calculate result again since   
  8.         // color value must be  between and 255.  
  9.         for int 0256*tableSize; i++  
  10.             divide[i] i/tableSize;   
  11.   
  12.         int inIndex 0 
  13.           
  14.         //   
  15.         for int 0height; y++  
  16.             int outIndex y;  
  17.             int ta 0tr 0tg 0tb 0// ARGB -> prepare for the alpha, red, green, blue color value.  
  18.   
  19.             for int -radius; <= radius; i++  
  20.                 int rgb in[inIndex ImageMath.clamp(i, 0width-1)]; // read input pixel data here. table size data.  
  21.                 ta += (rgb >> 240xff 
  22.                 tr += (rgb >> 160xff 
  23.                 tg += (rgb >> 80xff 
  24.                 tb += rgb 0xff 
  25.              
  26.   
  27.             for int 0width; x++ // get output pixel data.  
  28.                 out[ outIndex (divide[ta] << 24(divide[tr] << 16(divide[tg] << 8divide[tb]; // calculate the output data.  
  29.   
  30.                 int i1 x+radius+1 
  31.                 if i1 widthMinus1  
  32.                     i1 widthMinus1;  
  33.                 int i2 x-radius;  
  34.                 if i2 0  
  35.                     i2 0 
  36.                 int rgb1 in[inIndex+i1];  
  37.                 int rgb2 in[inIndex+i2];  
  38.                   
  39.                 ta += ((rgb1 >> 240xff)-((rgb2 >> 240xff);  
  40.                 tr += ((rgb1 0xff0000)-(rgb2 0xff0000)) >> 16 
  41.                 tg += ((rgb1 0xff00)-(rgb2 0xff00)) >> 8 
  42.                 tb += (rgb1 0xff)-(rgb2 0xff);  
  43.                 outIndex += height; // per column or per row as cycle...  
  44.              
  45.             inIndex += width; // next (i+ column number n, n=1....n-1)  
  46.          
  47.     }