
1.4 图像滤波与锐化算法
图像滤波与锐化实际上是图像处理领域比较大也比较重要的两个内容模块,可以单独成书。这里放在一起讲解,主要原因是在美颜算法的实际应用中,离不开图像滤波和锐化。美颜中的磨皮算法实际上就是以图像滤波算法为基础来实现的,而锐化则是磨皮美白之后,对图像整体清晰度的修复与增强。
本节给大家介绍如下几种常用的图像滤波算法和锐化算法:
· 图像均值滤波
· 图像高斯滤波
· 图像拉普拉斯锐化
· 图像USM锐化
注意:本书原则上只简单介绍基础图像算法,主要是针对滤镜、美颜美妆内容所做的一些基础构建,所以,不会介绍大量的专业图像算法内容,如有需要,读者可以自行查找相关专业书籍。
1.4.1 图像均值滤波
图像均值滤波算法是常用的线性滤波算法,也是一种局部空间域处理算法,由于其速度快,在很多场合被用来替代高斯滤波算法。顾名思义,图像均值滤波就是求取以当前像素为中心,某半径大小的正方形框内所有像素的均值,以此均值作为当前中心像素的滤波结果,具体算法如下所述。
假设像素P(i, j)为一张图像中(i, j)位置的像素,以P为中心,做半径为 2R+1大小的正方形邻域S,邻域S内的像素数量为M,均值滤波之后的结果为P0:

上述算法是标准均值滤波算法,在实际应用中速度较慢,一般无法满足大半径实时处理的需求。建议大家使用基于积分图的快速均值滤波算法或者基于直方图计算的快速均值滤波算法,这两种算法速度较快,对于低分辨率图像基本可以实现实时处理。
关于基于直方图计算的快速均值滤波算法,可参阅参考资料[5]中介绍的计算方法,这里给大家解释一下。
如图 1.35 所示,在一张图像中,如果要计算 A 像素的均值滤波结果值,那么,需要计算图中左侧红色阴影区域和黄色区域所有像素的和 SA,然后计算出均值结果。这里图中的滤波半径为2,也就是以A为中心的5×5矩形框,像素总数是25。

图1.35 基于直方图计算的快速均值滤波示意图
如果要计算B像素的均值滤波结果值,也就是在水平方向上计算A的下一个像素的均值滤波结果值,那么需要计算黄色区域和绿色阴影区域所有像素的和SB,然后计算出对应B像素的均值滤波结果值。
实际上可以发现,在两次计算中,我们重复计算了黄色区域,因此,大大增加了计算量。
所谓的快速算法,就是在计算SB的结果时,只需从SA中减去红色阴影区域,再加上绿色阴影区域,而不需要重新计算黄色区域。水平平移计算可以这样进行,垂直方向亦是如此。在大半径的情况下,实际的计算量是红色阴影区域和绿色阴影区域,因此速度大大加快,复杂度是O(n)。算法的伪代码如下:

图像均值滤波的效果如图1.36所示。

图1.36 图像均值滤波的效果
编程实现
我们使用C语言实现基于直方图的快速均值滤波算法与标准均值滤波算法:




图像均值滤波 DEMO界面如图 1.37所示,默认为快速均值滤波,勾选“标准滤波算法”复选框后,会执行标准均值滤波,速度较慢。

图1.37 图像均值滤波DEMO界面
本节所有代码工程及DEMO见代码包中1.5.1文件夹中的文件。
1.4.2 图像高斯滤波
高斯低通滤波(简称高斯滤波)是空间域中的一种线性平滑滤波,属于低通滤波器。高斯滤波主要用来消除高斯噪声或者用于模糊图像。
通俗来讲,高斯滤波实际上就是对图像进行加权平均计算,当前像素的滤波值就是对当前像素所在邻域范围内,做所有像素的加权平均,而权重是根据高斯函数计算生成的。图像的高斯滤波的过程也可以理解为模板算子卷积的过程,模板算子就是根据高斯半径不同,生成的不同大小的高斯权重模板。
我们将从一维高斯滤波讲起,让大家理解如何对一张二维图像进行高斯滤波处理。我们说过,高斯滤波可以理解为模板卷积的过程,那么重点就是高斯模板的计算,这里从高斯函数的定义看起。
一维高斯函数如下:

二维高斯函数如下:

其中,σ是高斯滤波的方差。
对于二维高斯函数,它的分布如图1.38所示。

图1.38 二维高斯分布
对于二维高斯函数,我们设置两个参数:高斯半径 r和方差 sigma,由半径 r可以得到一个(2×r+1)×(2×r+1)大小的高斯核模板,这个模板计算函数的代码如下(包含了权重归一化):

我们设置参数r=1,sigma=1.0,则得到一个3×3的高斯模板,如下所示:

通常,在图像处理中使用的高斯函数定义如下(对高斯分布做了一定的简化):

使用该公式得到3×3的高斯模板,如下所示:

对模板进行修正,即可得到我们常用的3×3经典模板:

这就是经典高斯模板的计算过程,半径不同,可以得到不同的模板,通常使用的 3×3 和5×5的经典模板如下:

得到高斯模板后,我们用它对图像进行卷积,就可以得到高斯滤波的结果图像了。由于直接使用二维高斯函数进行高斯滤波计算量巨大,影响图像处理的速度,因此,我们采用快速算法,即将二维高斯函数分解为如下公式:

这个公式可以理解为先对图像按行进行一次一维高斯滤波,再对结果图像按列进行一次一维高斯滤波。而两次高斯滤波,在相同半径的情况下,高斯计算得到的权重值是相同的,避免了重复计算,因此,速度将大大加快。
高斯滤波效果图如图1.39所示。

图1.39 高斯滤波效果图
编程实现
我们使用C语言实现快速高斯滤波算法,代码如下:



高斯算法DEMO的效果如图1.40所示。

图1.40 高斯算法DEMO的效果
上述就是高斯滤波算法的计算过程。高斯滤波应用广泛,在各种“高深”的算法中都经常会出现它的身影。在美颜磨皮操作中,常用的平湖磨皮法就是基于高斯滤波来实现的。在美妆章节,美妆模板的制作等也都离不开高斯滤波效果,对于初学者,对本节内容可以细细体会。
本节所有代码工程及DEMO见代码包中1.5.2文件夹中的文件。
1.4.3 图像拉普拉斯锐化
图像锐化就是补偿图像的轮廓,增强图像的边界及灰度跳变部分,从而使模糊的图像变得清晰。这是一个很大的话题,每年相关的论文都数不胜数,而在这里我们只讲其中很小很常用的一个算法—拉普拉斯(Laplace)锐化。
首先要知道 Laplace 是谁?Laplace 是法国著名的天文学家和数学家皮埃尔-西蒙·拉普拉斯侯爵,而拉普拉斯算子正是为了纪念 Laplace 首次使用该算子而命名的。然后我们来介绍为什么讲解这个算法。其实,在视频或者摄像头实时处理图像的过程中,往往需要对图像做一些边缘细节的增强,这时,由于拉普拉斯算法简单、速度快,因而备受青睐。
拉普拉斯锐化实际上是一个拉普拉斯算子模板的图像卷积计算,同前面所述的高斯模板类似,只不过这里的权重模板是拉普拉斯算子,这样讲初学者可能就很容易理解了。常用的拉普拉斯算子模板有4邻域模板和8邻域模板,如下所示:

假设有像素P(x, y),拉普拉斯锐化结果为G(x, y)。
对于4邻域模板,拉普拉斯算子的公式如下:

对于8邻域模板,拉普拉斯算子的公式如下:

拉普拉斯锐化计算:

拉普拉斯锐化效果如图1.41所示。

图1.41 拉普拉斯锐化效果
编程实现
我们使用C语言实现拉普拉斯锐化算法,代码如下:


拉普拉斯锐化算法的代码比较简单,大家可参见本节代码工程文件。本节所有代码工程及DEMO见代码包中1.5.3文件夹中的文件。
1.4.4 图像USM锐化
图像USM锐化即Unsharp Masking[6],是数字图像处理软件中常用的锐化算法,它可以去除细小的干扰细节和噪声,比拉普拉斯等卷积锐化算法效果更加可信,主要表现在边界清晰和细小噪声较少上。
经典 USM 锐化技术实际上是通过增强图像的高频内容(高频内容代表图像细节部分)来增强图像的视觉效果的,如图1.42所示。

图1.42 经典USM锐化示意图
在图1.42中,x为输入原图信号,y为输出锐化结果图像信号,z为校正信号,λ表示锐化强度因子。其中,z一般通过对x使用高通滤波器得到。在经典USM锐化中,使用的是拉普拉斯算子,公式如下:

在PS中,也提供了USM锐化功能,界面如1.43所示。

图1.43 PS中的USM锐化
我们以PS为例,来详解USM锐化算法。
PS中的USM锐化有三个参数,分别是半径Radius、数量Amount和阈值Threshold,假设原图为S,锐化结果为D,算法逻辑如下。
①根据半径Radius参数,对S进行高斯滤波并得到图A。
②计算校正信号Z:

③根据Z和Threshold计算二值蒙版Mask M:

④根据半径Radius对M进行高斯滤波,得到Alpha通道:

③根据Amount和Alpha计算D:

PS中的USM锐化效果如图1.44所示。

图1.44 PS中的USM锐化效果(Amount=100、Radius=100、Threshold=20)
编程实现
我们使用C语言实现USM锐化算法,代码如下:



本节介绍的算法与PS中的USM锐化效果对比如图1.45所示,效果基本一致。

图1.45 本节算法与PS中的USM锐化效果对比(Amount=100、Radius=100、Threshold=20)
本节所有代码工程及DEMO见代码包中1.5.4文件夹中的文件。