引言:
高斯模糊可以很好的模拟镜头焦外成像视觉效果。运用这种效果可以增强画面的层次感、突出画面的主体。在iOS7中这种效果被广泛运用:
原理:
当成像平面偏离焦平面的时候,景象上多个位置点射出的光线穿过了成像平面上的一个点。在图像处理中,我们通过对一个像素的附近像素求加权平均的方式来模拟这种焦外成像的效果,输出图像的一个像素的颜色是原图像相同位置附近的像素颜色的加权平均值。
实施:
接下来我们来实现这种图像像素加权平均。
如下图一个像素e和它的8个相邻像素abcdfghi,当所有的相邻像素的权重都相同的时候,输出图像的e位置的值就是e'=(a+b+c+d+e+f+g+h+i)/9,我们把这个处理过程叫图像的均值模糊,也叫均值滤波。这其实是也一种最简单的图像去噪算法。
为了方便计算和描述,我们加入权重矩阵的概念。上述的均值模糊算法用到的权重矩阵如下图所示:
运算处理时,我们只需将各像素的值乘以矩阵中对应位置的权重值并累加,最后将结果除以权重的总和。用这种方式描述也非常直观,我们看到矩阵中每个位置的值都相同,就可以知道每个位置对结果作的贡献是相同的。现在我们已经可以用上面的原理实现一个简单的图像模糊算法了,而且如果你还发现了一些规律,可以很高效的实现这个算法。
引入半径和高斯分布:
但是,通过上述算法得到的结果和想像中的结果还差的很远。其原因有两点:1.参与计算的像素和实际情况相比太少 2.由于相对位置不同,实际情况下各个像素的权重值也不同。
我们通过扩展权重矩阵的行列数来引入更多的附近像素。为了使矩阵以中心像素对称,这个矩阵的行列数必须是大于1的奇数。我们半径来表示这个矩阵的大小,当半径等于1时,说明这是一个3X3的矩阵。同样半径为2说明是个5X5的矩阵,以此类推。
另外我们假设一束入射的光线穿过成像平面的位置是概率性的,但是由于受到透镜的约束,越靠近成像平面上的某点,穿过的概率越大,这时我们想到了正态分布。高等数学中我们就分析过,为什么这种分布往往能很好的拟合自然界的一些概率事件。下图是一个正态分布的曲线图:
由于我们处理的图像需要在二维的面上来分析这个概率分布问题,所以我们需要一个二维的正态分布函数。正态分布的密度函数叫做"高斯函数"(Gaussian function)。我们到现在终于知道“高斯模糊”中高斯的含义了,一维的高斯函数是:
其中,μ是x的期望值,σ是x的方差。我们将中心位置的值定为0,所以这种情况下的期望值为0,我们可以得到下式:
另外为了方便计算,我们讨论当σ=1的情况下的正态分布,这时我们得到的是一个标准正态分布:
根据一维高斯函数,可以推导得到二维的高斯函数:
这个二维高斯函数形状是这样的:
现在我们给出任一半径都可以通过这个二维的高斯函数获得一个高斯分布的权重矩阵。我们还对从这个二维高斯函数获得的权重做归一化,这样我们就不需要再对最后的累加值做除法运算了。这里所谓归一化其实就是将矩阵乘以一个系数,使矩阵所有位置的值累加起来等于一。
可行性:
好了现在开始分析这种算法的可行性。根据经验,当高斯核半径为20的时候一般能达到很好的模糊效果。这样我们每处理一个像素需要考虑附近41*41=1681个像素,每个像素需要进行一次乘法和一次加法。当我们要处理512×512大小图片时,我们需要分别进行512×512×1681=440664064次乘法和除法。在移动平台上我们往往需要处理大于512×512的图像,所以基本无法实施这种特效算法。
下一篇我们开始讨论如何优化算法,并通过RenderScript高效的实现高斯模糊。优化后针对一副900×900的图像,Nexus4上,处理时间平均只要15ms左右。
下面是待处理的原图:
Nexus4上最终效果图和处理时间: