平滑线性滤波器
图像去噪这一块内容庞杂,我本来打算和形态学处理一样用一篇博客介绍完整,但是当所有目录列出来后,还是打算分4篇博客进行介绍分别为空间域3篇和频率域1篇
这篇博客主要是空间域线性滤波
噪声类型为:
- 高斯噪声,
- 白噪声,
- 胡椒噪声,
效果方面为:
- 不(或者是非刻意)保边缘
- 保边缘
均值滤波
善于高斯噪声,其中分为两类均值滤波分别为:算术均值,几何均值
算术均值:即求模板内的像素值平均值,理解:
- 假如当前点为平滑区域的点,那么与周围像素一起算均值后,其值必定保持不变
- 假如当前点为噪声点,那么与周围像素一起算均值后,其值必定减小,达到去噪效果
- 如果当前点为边缘区域的点,那么与周围像素一起算均值后,其值必定减小,则使得边缘变得模糊
几何均值:算是一个鸡肋滤波,基本无法使用,虽然可以有保边缘的作用,但是效果并不突出,在博客后面我补充了一个新的保边缘滤波故这里不做介绍
故算术均值滤波去高斯噪声不保边缘
代码如下: 其中不包含
import cv2
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
def show(f, s, a, b, c):
plt.subplot(a, b, c)
plt.imshow(f, "gray")
plt.axis('on')
plt.title(s)
# 高斯噪声函数单行
def wgn(x, snr):
snr = 10 ** (snr / 10.0)
xpower = np.sum(x ** 2) / len(x)
npower = xpower / snr
return np.random.randn(len(x)) * np.sqrt(npower)
def main():
original = plt.imread("lena.tiff", 0)
rows, cols = original.shape
original_noise = original.copy().astype(np.float64)
# 生成噪声图像,信噪比为10
for i in range(cols):
original_noise[:, i] += wgn(original_noise[:, i], 10)
mask = np.ones(9).reshape(3, 3)
ImageDenoise = np.zeros(original.shape)
for i in range(1, rows - 1):
for j in range(1, cols - 1):
ImageDenoise[i, j] = np.mean(original[i - 1:i + 2, j - 1:j + 2] * mask)
plt.figure()
show(original, "original", 2, 2, 1)
show(original_noise, "original_noise", 2, 2, 2)
show(ImageDenoise, "ImageDenoise", 2, 2, 3)
show(original - ImageDenoise, "original - ImageDenoise", 2, 2, 4)
plt.show()
if __name__ == '__main__':
main()
效果如下:
谐(逆谐)波均值滤波
这个主要针对的盐噪声或者胡椒噪声,但是这个基本上也不会使用,因为处理上面两种噪声统计排序滤波有着极大优势!!!(下篇会有介绍),故这里不做特别介绍,读者只需要明白其中思想即可
有选择保边缘平滑滤波(保边缘)
其中在高斯噪声方面表现较差,而对于椒盐噪声表现良好,这里代码给出处理椒盐噪声的效果(噪声个数为2 * max(行数,列数)),需要理解为什么能够保边缘才是这个滤波的关键!!!
代码如下:可以看出残差图基本上就是噪声模式
# 添加椒盐噪声
def pepperNoise(count, I):
rows, cols = I.shape
newI = np.copy(I)
for i in range(count):
if i % 2 == 0:
newI[random.randint(0, rows - 1)][random.randint(0, cols - 1)] = 0
else:
newI[random.randint(0, rows - 1)][random.randint(0, cols - 1)] = 255
return newI
# 有选择保边缘平滑方法
def edgeFilter(noise):
rows, cols = noise.shape
deNoise = np.zeros(noise.shape)
# 生成滤波模板下标数组
maskRect = np.ones(9).reshape(3, 3)
maskPentTop = np.array([1, 1, 1, 1, 1, 1, 0, 1, 0]).reshape(3, 3)
maskPentLeft = np.array([1, 1, 0, 1, 1, 1, 1, 1, 0]).reshape(3, 3)
maskPentBottom = np.array([0, 1, 0, 1, 1, 1, 1, 1, 1]).reshape(3, 3)
maskPentRight = np.array([0, 1, 1, 1, 1, 1, 0, 1, 1]).reshape(3, 3)
maskHexagon1 = np.array([1, 1, 0, 1, 1, 1, 0, 1, 1]).reshape(3, 3)
maskHexagon2 = np.array([0, 1, 1, 1, 1, 1, 1, 1, 0]).reshape(3, 3)
maskHexagon3 = np.array([0, 1, 1, 1, 1, 1, 1, 1, 0]).reshape(3, 3)
maskHexagon4 = np.array([1, 1, 0, 1, 1, 1, 0, 1, 1]).reshape(3, 3)
for i in range(2, rows - 2):
for j in range(2, cols - 2):
maskList = []
array_var = []
maskList.append(noise[i - 2:i + 1, j - 2:j + 1] * maskHexagon1)
maskList.append(noise[i - 2:i + 1, j - 1:j + 2] * maskPentTop)
maskList.append(noise[i - 2:i + 1, j:j + 3] * maskHexagon2)
maskList.append(noise[i - 1:i + 2, j - 2:j + 1] * maskPentLeft)
maskList.append(noise[i - 1:i + 2, j - 1:j + 2] * maskRect)
maskList.append(noise[i - 1:i + 2, j:j + 3] * maskPentRight)
maskList.append(noise[i:i + 3, j - 2:j + 1] * maskHexagon3)
maskList.append(noise[i:i + 3, j - 1:j + 2] * maskPentBottom)
maskList.append(noise[i:i + 3, j:j + 3] * maskHexagon4)
array_var.append(np.var(noise[i - 2:i + 1, j - 2:j + 1] * maskHexagon1))
array_var.append(np.var(noise[i - 2:i + 1, j - 1:j + 2] * maskPentTop))
array_var.append(np.var(noise[i - 2:i + 1, j:j + 3] * maskHexagon2))
array_var.append(np.var(noise[i - 1:i + 2, j - 2:j + 1] * maskPentLeft))
array_var.append(np.var(noise[i - 1:i + 2, j - 1:j + 2] * maskRect))
array_var.append(np.var(noise[i - 1:i + 2, j:j + 3] * maskPentRight))
array_var.append(np.var(noise[i:i + 3, j - 2:j + 1] * maskHexagon3))
array_var.append(np.var(noise[i:i + 3, j - 1:j + 2] * maskPentBottom))
array_var.append(np.var(noise[i:i + 3, j:j + 3] * maskHexagon4))
deNoise[i, j] = np.mean(maskList[array_var.index(min(array_var))])
return deNoise
效果如下:
总结:天下没有免费的午餐,当保边缘的时候必定会牺牲一定的速度
转载我博客应当经我允许,至少要把原文链接放在文章最前面,这是对本人辛苦原创基本的尊重。