中值滤波将图像的每个像素用邻域 (以当前像素为中心的正方形区域)像素的中位数
代替 。与邻域平均法类似,但计算的是中值。
用scipy.signal.medfilt()实现中值滤波
函数原型:
scipy.signal.medfilt(volume, kernel_size=None)
参数:
- volume: N维输入数组。
- kernel_size: 一个标量或元组,代表每个维度中中值滤波窗口的大小(即取多少个值的中值),默认值为3。
中值滤波技术能有效抑制噪声,通过把数字图像中一点的值用该点周围的各点值的中位数来代替,让这些值接近,以消除原数据(图像or时序数据)中的噪声。
signal的medfilt()方法传入一个参数:
import random
import numpy as np
import scipy.signal as signal
x=np.arange(0,100,10)
random.shuffle(x)
pint(x)
x = signal.medfilt(x,3) #一维中值滤波
pint(x)
"""
输出:array([60, 40, 70, 0, 50, 30, 90, 80, 10, 20])
array([40., 60., 40., 50., 30., 50., 80., 80., 20., 10.])
"""
signal的medfilt()方法传入两个参数:第一个参数是要作中值滤波的信号,第二个参数是邻域的大小(奇数)。如邻域为3即是每个点自己和上下左右各一个点(共9个点)成为一个邻域。在每个位置的邻域中选取中位数
替换这个位置的数。如果邻域中出现没有元素的位置,那么以0补齐。
x = np.random.randint(1,1000,(4,4))
print(x,"\n")
x = signal.medfilt(x,(3,3)) #二维中值滤波
print(x)
"""
输出:
[[ 14 442 710 256]
[839 102 372 937]
[ 70 638 506 684]
[118 769 608 666]]
[[ 0. 102. 256. 0.]
[ 70. 442. 506. 372.]
[102. 506. 638. 506.]
[ 0. 118. 608. 0.]]
"""
中值滤波在时序数据上的效果
import scipy.signal as signal
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
n = 50
y = np.sin(np.linspace(0, 10, n)) + np.random.rand(n)
y_med = signal.medfilt(y, kernel_size=5)
plt.figure()
plt.plot(y, 'r--', label='y')
plt.plot(y_med, 'b-.', label='y_med')
plt.legend()
plt.show()
可以看出经中值滤波处理后的数据(蓝色线)相对原数据(红色线)较平滑了许多
中值滤波在图像上的应用效果
import cv2
import numpy as np
url="test.png"
img=cv2.imread(url)
# 加上椒盐噪声
# 灰阶范围
w=img.shape[1]
h=img.shape[0]
newimg=np.array(img)
# 噪声点数量
noisecount=5000
for k in range(0,noisecount):
xi=int(np.random.uniform(0,newimg.shape[1]))
xj=int(np.random.uniform(0,newimg.shape[0]))
newimg[xj,xi]=255
# 中值滤波去噪(平滑图片)
lbimg=cv2.medianBlur(newimg,3)
cv2.imshow('lbimg',lbimg)
# 添加了噪音的图片
cv2.imshow('newimg',newimg)
cv2.waitKey()
cv2.destroyAllWindows()