中值滤波器原理
图像处理中最著名的统计排序滤波器是中值滤波器,即用一个预定义的像素领域中的灰度中值来代替像素的值:
其中是以(x,y)为中心的领域,包含中心点自己,在领域中找到中值,并用中值代替中心点的像素值。例如,对于图像中的一个像素点a,其灰度值为6,我们取大小为3×3的领域,灰度值如下表所示:
1 | 2 | 3 |
7 | 6 | 99 |
8 | 5 | 4 |
我们进行排序后发现其中值为5,故使用5来代替原来的灰度值6。很显然,在小区域内正常像素差距较小,故使用中值替代时所造成的差异较小,但是中值滤波器能很好的降低某些随机噪声,例如上例中的99,尤其对于椒盐噪声有很好的滤除效果。
Python实现
import cv2
import numpy as np
import matplotlib.pyplot as plt
def noise(img, snr):
h = img.shape[0]
w = img.shape[1]
img1 = img.copy()
sp = h * w # 计算图像像素点个数
NP = int(sp * snr)
randx = 1
randy = 1 # 计算图像椒盐噪声点个数
for i in range(NP):
while (img1[randx, randy] == 0 or img1[randx, randy]== 255):
# 确保随机得到的像素没有被污染
randx = np.random.randint(1, h - 1) # 生成一个 1 至 h-1 之间的随机整数
randy = np.random.randint(1, w - 1) # 生成一个 1 至 w-1 之间的随机整数
if np.random.random() <= 0.5: # np.random.random()生成一个 0 至 1 之间的浮点数
img1[randx, randy] = 0 # 随机放置椒噪声、盐噪声
else:
img1[randx, randy] = 255
return img1
def median(img, size): # img为输入图像 size为中值滤波器大小
height = img.shape[0]
wide = img.shape[1]
img1 = np.zeros((height, wide), np.uint8) # 用于存放新的图像
for i in range(int(size/2), height - int(size/2)):
for j in range(int(size/2), wide - int(size/2)):
Adjacent_pixels = np.zeros(size * size, np.uint8)
s = 0
for k in range(-1 * int(size / 2), int(size / 2)+1):
for l in range(-1 * int(size / 2), int(size / 2)+1):
Adjacent_pixels[s] = img[i + k, j + l]
s += 1
Adjacent_pixels.sort() # 寻找中值
median = Adjacent_pixels[int((size * size - 1) / 2)] # 将中值代替原来的中心值
img1[i, j] = median
return img1
image = cv2.imread(r'11.jpg', cv2.IMREAD_GRAYSCALE)
print(image)
imagen = noise(image, 0.23) # 添加噪声
plt.subplot(1, 3, 1)
plt.imshow(image, plt.cm.gray)
plt.title('original')
plt.subplot(1, 3, 2)
plt.imshow(imagen, plt.cm.gray)
plt.title('noise')
image1 = median(imagen, 5)
plt.subplot(1, 3, 3)
plt.imshow(image1, plt.cm.gray)
plt.title('median')
plt.show()
实现结果
可以看出,中值滤波器对椒盐噪声的去除效果差强人意。