高斯模糊的实现方法

转载;http://blog.csdn.net/markl22222/article/details/10313565  

请跳转看原文,本文只是对其的收藏,方便以后查看


一、高斯模糊是什么

模糊算法,不论是使用哪种算法,目的都是为了让图片看起来不如原来那么清晰。

清晰的图片,像素间的过渡会较为干脆利落,简而言之,就是像素之间的差距比较大。
而模糊的本质,其实就是使用某种算法把图像像素和像素之间的差距缩小,让中间点和周围点变得差不多;即,让中间点取一个范围内的平均值。
模糊到了极致,比如用于计算模糊的取值区域为整张图片,就会得到一张全图所有像素颜色都差不多的图片:


左边是原图,右边是彻底模糊之后的对比图

计算模糊的取值区域就是滤镜区域,那么关键就是,我们采用什么曲线函数来生成平均值了。

假设滤镜区域为正方形,且半径为r,我们可以用如下曲线函数来计算图片上某一个点的值:


这是一个非常简单的直线函数,求得的点值即为算术平均值,图片上某个点的值仅和模糊半径r有关,与坐标的位置无关。

由此我们可以得到用于模糊图像的滤镜算法:


每个像素通道的最大值不能超过255,若赋予的值超出了通道最大值,则将通道值限制在最大值上。

使用上面的算法,设置滤镜半径为5,处理出来的图片效果如下:


左边是原图,右边是对比图

模糊成功了,但效果有些不尽人意,图片的一些边缘细节模糊得并不柔和,感觉像没戴眼镜的近视眼看起来的效果。

从上面的算法里我们可以看出,滤镜中填充的每一个值,可以看做是一个权重。在处理图像的时候,通过它计算出滤镜范围内每个像素的权重值,最后将它们相加,得到的就是滤镜中心点的像素值。
使用上面的模糊算法,在处理图片的时候,对所有的像素点是一视同仁的。但实际上,离中心点越远的点,重要性应该越低才更合理。
也就是说,越靠近滤镜边缘的像素,权重更小才会更符合实际。

高斯分布,即正态分布曲线,形状大概如下图:


图片来源: http://zh.wikipedia.org/wiki/File:Standard_deviation_diagram.svg

它就是一个可以计算出符合上面要求的权重分布的函数,对应的二维形式如下:

使用高斯分布曲线作为滤镜算法的模糊算法,称之为高斯模糊


二、高斯模糊算法实现

设置滤镜半径为5,通过与前文一样的遍历算法,我们可以得到下面的模糊效果:


左边是原图,右边是对比图

这个效果不够明显,我们可以设更大一点的滤镜,比如10,处理出来的效果如下:


左边是原图,右边是对比图

好了,模糊成功了。效率怎么样呢?
在我的电脑上(i3M330,2.13G),使用 半径10 的滤镜处理 400 × 649 的图片,Debug版本需要大约 8s 左右,Release版本则为916ms。
这个速度就算在Release下也偏慢了。

研究一下我们的算法:
当滤镜半径为r时,算法的时间复杂度是O(x × y × (2r)²)。
能否降低一点呢?


三、高斯模糊算法优化

引用维基百科里的原文:

“除了圆形对称之外,高斯模糊也可以在二维图像上对两个独立的一维空间分别进行计算,这叫作线性可分。这也就是说,使用二维矩阵变换得到的效果也可以通过在水平方向进行一维高斯矩阵变换加上竖直方向的一维高斯矩阵变换得到。”

这个特征让我们可以使用一维的高斯函数,在横纵两个方向上分别处理一次图像,得到和二维高斯函数一样的效果。
使用一维高斯函数,算法的时间复杂度就变为O(2 × x × y × 2r),两相比较,算法效率高出r倍。

一维形式的高斯函数如下:



四、其它模糊算法

从上面的文字里,我们已经知道了高斯模糊算法其实就是利用高斯函数或者说曲线,生成模糊滤镜,然后对图像像素做处理的算法。
那么我们可以考虑使用其它曲线来作为我们的模糊曲线么?

当然是可以的。
文章的最开始就使用了最简单的算术平均值曲线作为模糊曲线,只是实际的效果较为一般。

我们可以再尝试其他的曲线函数,比如直线函数:


求绝对值是为了让函数曲线保持“中间高两边低”

使用其他函数得到的滤镜算法和处理的图片效果本文就不再一一赘述了。感兴趣的朋友可以下载文后所附的代码。

附件里的模糊算法实现在filter.h中,VC和gcc编译器下均编译通过。测试平台基于win32下的Qt 5.0.1,编译器为MinGW 4.7。


代码下载:TestGauss2.zip


你可能感兴趣的:(Android--自定义控件)