本篇主要介绍常见降噪算法之一的高斯低通滤波(Gaussian Low Pass Filter)。获取文中代码和图像请移步我的Github仓库:Gaussian Denoising
Using Python & Matlab。
一、正态分布(Normal Distribution)与高斯函数(Gaussian Function)
上一篇里我们谈到了,散粒噪声(Shot Noise,Poisson Noise)、闪烁噪声(Flicker Noise)、布朗噪声(Brown
Noise)均在一定程度上服从正态分布。正态分布又称高斯分布(Gaussian
Function),是在统计、自然科学和社会科学上非常常用的一个连续概率分布模型。这种概率分布非常奇妙,因为有相当多随机现象的发生如心理学测试分数、光子计数、红细胞数量等,均被发现趋近于正态分布。
正态分布概率密度函数图像
正态分布的概率密度函数是高斯函数的一个实例。其均值为μ,标准差为σ,当σ为1时,称作标准正态分布,如上图红色曲线。
由其特性可知,当标准差σ确定时,不论均值μ为多大,函数图像的形状都是一样的,不同的只是中轴线的位置。
正态分布的高斯函数表达式
正态分布中一些值得注意的量:
· 密度函数关于平均值μ对称
· 平均值μ与它的众数(statistical mode)以及中位数(median)同一数值。
· 函数曲线下68.268949%的面积在平均数μ左右的一个标准差σ范围内。
· 95.449974%的面积在平均数左右两个标准差σ的范围内。
· 99.730020%的面积在平均数左右三个标准差σ的范围内。
· 99.993666%的面积在平均数左右四个标准差σ的范围内。
· 函数曲线的拐点(inflection point)为离平均数μ一个标准差σ距离的位置。
二维图像的高斯分布概率图像
二维图像的高斯分布概率图像如图所示,为由中心向四周概率密度愈来愈低的峰状结构。
二、高斯低通滤波(Gaussian Low Pass Filter)
高斯低通滤波又称高斯模糊(Gaussian Blur),是一种图像模糊滤波器,使用正态分布来计算图像中每个像素的变化。
其基本方法为,使用高斯函数生成一个卷积核(低通过滤器),卷积核为一个满足高斯概率分布的二维元组,元组中的元素为高斯函数在该点的概率密度值,由中心向四周逐渐降低。对于一个确定大小的卷积核,其各个点的概率密度值仅取决于高斯函数中的标准差σ。
3X3大小,高斯分布σ=1情形下的卷积核
高斯滤波操作即使用该卷积核在源图像上滑动,在经过的像素区域,按卷积核所确定的概率关系,对源图像进行加权取均值操作,得到的均值,即为中心像素经过处理后的值。最终得到过滤后的图像。卷积核越大、标准差σ越大,图像越模糊,反之则越清晰。
在Adobe
Photoshop、GIMP、Paint.NET等专业图像处理软件中应用广泛。由于常见图像噪声有不少遵循高斯分布,故常用高斯低通滤波的方法来处理这些噪声。不过值得注意的是,高斯滤波也称作高斯模糊,不少人应该在Adobe
Photoshop中见到过这个滤镜,从它的名字便可看出,使用这种方法来处理图像噪声,缺点便是会让图像变得模糊。这是因为高斯低通滤波器在处理像素的时候是不会做出任何区分的,无论噪点还是有效像素均会被处理。很多手机夜间拍照得到的图像涂抹感很强,一部分原因就是处理生成图像的算法中包含高斯低通滤波的操作。
三、处理步骤
由以上介绍可以得出,要对图像进行高斯滤波,首先要确定一个卷积核,然后由卷积核与源图像进行卷积,最终得到滤波后的图像。
高斯低通滤波处理图像的步骤
而源图像是确定的,此处的卷积核由高斯函数得出,因此只需确定卷积核的大小以及高斯函数的具体概率密度分布即可,亦即ksize(Kernel
Size)和Sigma(σ)。因此我们只需要建立一个参数为源图像、ksize、Sigma的高斯滤波函数,对源图像进行滤波输出即可。
四、Python实现:
Python语言的优势之一便是有着良好的社区贡献内容,许多常用算法均有成熟的模组供直接调用,此处我们使用来自OpenCV的gaussian_blur函数即可完成高斯滤波处理。处理后使用matplotlib中的pyplot工具进行图像绘制,然后用OpenCV的cv2.imwrite()函数输出处理后的图像。
OpenCV Image Processing Docs中的cv2.gaussian()函数文档
需要注意的是这个函数的几个参数。src,也就是源图像,需为多维数组类型(ndarray),故需先用cv2.imread()函数对源图像进行读取和处理。ksize,也就是卷积核的大小,为元组类型,此处选择5X5大小的卷积核来处理,可手动修改为其他大小。sigma,也就是标准差,为浮点类型,此处设置为20,也可手动修改其他值。
本例程首先导入代码根目录下的sample.jpg文档,经过高斯滤波后和原图一并显示并输出滤波后的图像到PythonFilteredImage.jpg,保存在代码根目录下。
在Pycharm中查看进程中几个变量的数据类型
代码实现:
import cv2 # 导入OpenCV库
import matplotlib.pyplot as plt # 导入Matplotlib库,用于绘制图像
def gaussian_blur(input_image, ksize, sigma): # 高斯低通滤波函数
filtered_image = cv2.GaussianBlur(
input_image,
ksize,
sigma
) # cv2.gaussian_blur函数,用于对图像进行高斯滤波
return filtered_image
def show_image(order, input_image, title): # 图像显示函数
plt.subplot(1, 2, order) # 生成一个单行两列的图像显示窗口,传入图片顺序Order
plt.imshow(input_image) # 图像内容
plt.title(title) # 图像标题
def main():
input_image = cv2.imread('sample.jpg') # 读取工程目录下的sample.jpg文档作为输入即降噪对象
ksize = (5, 5) # 此参数用于修改滤波器大小
sigma = 1.5 # 此参数用于修改高斯低通滤波函数中的高斯半径大小
filtered_image = gaussian_blur(input_image, ksize, sigma)
show_image(1, input_image, 'Input Image') # 在图像窗口左侧显示原图
show_image(2, filtered_image, 'Filtered Image') # 在图像窗口右侧显示降噪后的图像
plt.show() # 绘制图像
cv2.imwrite('PythonFilteredImage.jpg', filtered_image) # 以jpg格式导出降噪后的图像文档到工程目录
if __name__ == "__main__":
main()
Pycharm运行结果
源图像
降噪后的图像
五、Matlab实现
Matlab在数学函数和算法方面的先天优势自不用说,可以看到,实现相同的功能,Matlab的代码数量比向来以简洁著称的Python还要少。此处我们直接使用Matlab内置的fspecial()函数来生成滤波器,并用imfilter()函数来将滤波器应用于源图像,最后用imwrite()函数输出处理后的图像。
Matlab Image Processing Toolbox Docs中的fspecial()函数文档
代码实现:
InputImage = imread('sample.jpg'); % 读取工程目录下的sample.jpg文档作为输入即降噪对象
InputImage = im2double(InputImage); % 将图像转换为双精度值,因Matlab不支持无符整型图像数据
% 生成高斯低通滤波器
ksize = 10; % 此参数用于修改滤波器大小
sigma = 20; % 此参数用于修改高斯低通滤波函数中的高斯半径大小
Filter = fspecial('gaussian',ksize,sigma); % 调用fspecial函数生成滤波器
FilteredImage = imfilter(InputImage,Filter,'replicate'); % 调用imfilter函数对图像和滤镜进行卷积操作,生成过滤后的图像
figure; % 绘制图像
subplot(121);imshow(InputImage);title('Input Image'); % 在图像窗口左侧显示原图
subplot(122);imshow(FilteredImage);title('Filtered Image'); % 在图像窗口右侧显示降噪后的图像
imwrite(FilteredImage,'MatlabFilteredImage.jpg'); % 以jpg格式导出降噪后的图像文档到工程目录
Matlab运行结果
源图像
降噪后的图像
参考文献: