目录
3.4 实验:均值滤波器与中值滤波器对椒盐噪声和高斯噪声的效果比较
一、图像复原
1、基本概念:
- 图像复原的一般过程:分析退化原因——建立退化模型——反向推演——恢复图像
- 图像增强:旨在改善图像质量,提高图像的可懂度,更偏向主观判断。即要突出所关心的信息,满足人的视觉系统,具有好的视觉效果。
- 图像复原:根据图像畸变或退化的原因,进行模型化处理,将质量退化的图像重建或恢复到原始图像。即恢复退化图像的本来面目,忠于原图像,因此必须根据一定的图像退化模型来进行图像复原。
- 图像复原方法思路:关键是要由退化后的图像估计出退化函数和噪声函数,然后可以得到恢复算子。恢复计算,可以在空域上进行恢复,也可以在频域上进行恢复。
增强与复原的比较:
图像的增强是一个主观的过程,其目的是改善图片的质量,对感兴趣的部分加以增强,对不感兴趣的部分予以抑制。而图像复原是一个客观的过程,针对质量降低或失真的图像,试图恢复其原始的内容或质量。复原技术是面向退化模型的,并且采用相反的过程进行处理,以便恢复出原图像。在进行图像复原之前要先建立起其退化模型,根据该模型进行图像复原。
2、课本中的图像退化过程建模为一个退化函数和一个加性噪声:
在空间域,h(x,y)称为点扩散函数(PSF),对于任何种类的输入,让h(x,y)作用于光源的一个点来得到退化的特征。
若H是线性的,空间不变的过程,则退化图像在空间域通过下式给出:
g(x,y)=h(x,y)∗f(x,y)+δ(x,y)
其中,h(x, y)是退化函数的空间表示,符号∗表示卷积。空间域的卷积和频域的乘法组成了一个傅里叶变换对,所以可以用等价的频域表示来写出前面的模型:
G(u,v)=H(u,v)F(u,v)+N(u,v)
在只有加性噪声的情况,可以通过一些噪声模型(例如高斯噪声,瑞利噪声,椒盐噪声等等)以及对这些噪声参数的估计,来选择合适的空间滤波器(如均值滤波器,中值滤波器)或者频率滤波器(带阻/带通滤波器,低通/高通滤波器,陷波滤波器)来进行滤波
二 、噪声模型
- 模拟噪声的行为和影响的能力是图像复原的核心。
- 噪声来源:主要来源于图像的获取和传输过程。例如,CCD摄像机获取图像,光照程度和传感器温度是生成图像中产生大量噪声的主要因素;传输过程受所用传输信道的噪声干扰。
1.一些重要的噪声模型
1.1 高斯噪声
概念:高斯噪声是指它的概率密度函数服从高斯分布(即正态分布)的一类噪声,是几乎每个点上都出现噪声、噪点深度随机的噪声。
概率密度函数:
方差:
均值:
曲线:
1.2 瑞利噪声
概率密度函数:
均值:
方差:
曲线:
1.3 伽马(爱尔兰)噪声
概率密度函数:
均值:
方差:
曲线:
注意:只有当分母是Γ(b)时,才是伽马噪声,如表达式中的,该密度近似称为爱尔兰密度
1.4 指数分布噪声
概率密度函数:
均值:
方差:
曲线:
这个PDF是当b=1时爱尔兰PDF的特殊情况。
1.5 均匀噪声
概率密度函数:
均值:
方差:
曲线:
1.6脉冲(椒盐)噪声
概率密度函数:双极脉冲噪声:
如果b>a,灰度值b在图像中将显示为一个亮点,相反,a的值将显示为一个暗点。若Pa或Pb为零,则脉冲噪声为单极脉冲。如果两者都不为零,尤其在它们近似相等时,脉冲噪声将类似于随机分布在图像上的胡椒和盐粉微粒,因此双极脉冲噪声也称为椒盐噪声。
曲线:
2.周期噪声
1.来源:主要是在图像获取过程中从电力或机电干扰中产生的。
2.是唯一的一种空间依赖性噪声(即该噪声不是对原图像某一区域的影响,而是对图像的整个空域都有影响)。空间上表现为周期
性,在频域中是孤立的点,因此常用频域的办法来滤除周期噪声。
3.噪声参数估计
典型的周期噪声参数是通过检测图像的频谱来进行估计的,但这仅仅适用于非常简单的情况。
通常采用的方法是截取一组“平坦”环境的图像,通过这部分图像的直方图形状与上节中几种典型噪声的直方图形状进行匹配,若形状是高斯,那么我们就说这个噪声是高斯噪声,继续计算它的均值和方差,得到需要的参数。
均值:
方差:
对于其他噪声,如瑞利、指数等,其参数a和b可以根据均值和方差计算得到。
三 、只存在噪声的复原——空间滤波
此时退化模型:
时域:
频域:
滤波器介绍:一个空间滤波器包括两个部分:
- 一个邻域,滤波器进行操作的像素集合,通常是一个矩形区域
- 对邻域中像素进行的操作
一个滤波器就是在选定的邻域像素上执行预先定义好的操作产生新的像素,并用新的像素替换掉原来像素形成新的图像。
通常,也可以将滤波器称之为核(kernel),模板(template)或者窗口(window)。
根据预定义的操作,可以将滤波器分为:
- 线性滤波器
- 非线性滤波器
而根据滤波器最终对图像造成的影响,可以将滤波器分为:
- 平滑滤波器 ,通常用于模糊图像或者去除图像中的噪声
- 锐化滤波器,突出图像中的边缘细节部分
3.1均值滤波器
- 算术均值滤波器
数学描述:
处理结果:模糊了结果,降低了噪声
缺点:对图像模糊较大
适用:适用于高斯噪声或均匀随机噪声
- 几何均值滤波器
数学描述:
处理结果:和算术均值滤波器相比,模糊后丢失更少的细节
适用:适用于高斯噪声或均匀随机噪声
- 谐波均值滤波器
数学描述:
处理结果:谐波均值滤波器对于“盐”噪声效果更好,但是不适用于“胡椒”噪声
适用:高斯噪声
- 逆谐波均值滤波器
数学描述:
其实Q称为滤波器的阶数,当Q值为正时,滤波器用于消除“胡椒”噪声;当Q值为负时,滤波器用于消除“盐”噪声。但它不能同时
消除两种噪声,当Q值为0时,逆谐波滤波器变为算术均值滤波器;当Q为-1时,逆谐波均值滤波器退变为谐波均值滤波器。
适用:脉冲噪声
缺点:必须知道是明噪声还是暗噪声
3.2顺序统计滤波器
顺序统计滤波器的响应是基于由滤波器包围的图像区域中像素点的排序,任一点的响应由排序结果决定。以中值滤波器为基础
- 中值滤波器
数学描述:
效果:具有良好的去噪能力,相同尺寸下比线性平滑滤波器引起的模糊较少
适用:对单极或双极脉冲噪声非常有效
- 最大值滤波器
数学描述:
适用:发现图像中的最亮点,故适用于去除“胡椒”噪声
- 最小值滤波器
数学描述:
适用:发现图像中的最暗点,适用于去除“盐”噪声
- 中点滤波器
数学描述:
适用:结合了顺序统计和求平均,对高斯和均匀随机分布的噪声有很好的效果
- 修正的阿尔法均值滤波器
数学描述:
适用:对多重混合的噪声有很好的效果
在邻域内取点g(s,t)最高灰度值的d/2和最低灰度值的d/2,用来代表剩余的mn-d个像素,由这些剩余像素点的平均值
形成的滤波器称为修正后的阿尔法均值滤波器
当d=0时,退变为算术均值滤波器;当d=(mn-d)/2时,退变为中值滤波器
3.3 自适应滤波器
自适应滤波器的行为变化基于由m*n矩形窗口Sxy定义的区域内图像的统计特性,它的性能要明显优于前面介绍的滤波器,代价是滤波器的复杂度。
- 自适应、局部噪声消除滤波器
数学描述:
性能:(1)如果为0,滤波器应该简单方晖g(x,y)的值
(2)如果局部方差与是高度相关的,那么滤波器要返回一个g(x,y)的近似值。
(3)如果两个方差相等,希望滤波器返回区域Sxy上像素的算术均值。
一个关键的问题是未知,需要进行估计,合理的估计会带来较好的滤波效果。
适用:防止由于缺乏图像噪声方差知识而产生的无意义结果,适用均值和方差确定的加性高斯噪声。
3.4 实验:均值滤波器与中值滤波器对椒盐噪声和高斯噪声的效果比较
python实现高斯噪声:
piture = cv2.imread("D:/Data/school.jpg")
piture = cv2.resize(cv2.cvtColor(piture,cv2.COLOR_BGR2RGB),(200,200))
plt.imshow(piture)
plt.axis("off")
plt.show()
gauss = np.random.normal(mean,sigma,(row,col,ch))
def GaussieNoisy(image,sigma):
row,col,ch= image.shape
mean = 0
gauss = np.random.normal(mean,sigma,(row,col,ch))
gauss = gauss.reshape(row,col,ch)
noisy = image + gauss
return noisy.astype(np.uint8)
plt.imshow(GaussieNoisy(piture,25))
plt.show()
高斯噪声图:
python实现椒盐噪声:
def spNoisy(image,s_vs_p = 0.5,amount = 0.004):
row,col,ch = image.shape
out = np.copy(image)
num_salt = np.ceil(amount * image.size * s_vs_p)
coords = [np.random.randint(0, i - 1, int(num_salt)) for i in image.shape]
out[coords] = 1
num_pepper = np.ceil(amount* image.size * (1. - s_vs_p))
coords = [np.random.randint(0, i - 1, int(num_pepper)) for i in image.shape]
out[coords] = 0
return out
plt.imshow(spNoisy(piture))
plt.show()
椒盐噪声图:
实验分析:在彩色图像情况下处理似乎肉眼分辨不够细致,细微的区别效果看起来不明显
改进:将图像灰度化,选取合适量级显示:
Grey_sp = R * 0.299 + G * 0.587 + B * 0.114
Grey_gs = R * 0.299 + G * 0.587 + B * 0.114
plt.imshow(Grey_sp, cmap='gray')
plt.imshow(Grey_gs, cmap='gray')
均值滤波与中值滤波python实现:
ef medium_filter(im, x, y, step):
sum_s = []
for k in range(-int(step / 2), int(step / 2) + 1):
for m in range(-int(step / 2), int(step / 2) + 1):
sum_s.append(im[x + k][y + m])
sum_s.sort()
return sum_s[(int(step * step / 2) + 1)]
def mean_filter(im, x, y, step):
sum_s = 0
for k in range(-int(step / 2), int(step / 2) + 1):
for m in range(-int(step / 2), int(step / 2) + 1):
sum_s += im[x + k][y + m] / (step * step)
return sum_s
def convert_2d(r):
n = 3
window = np.ones((n, n)) / n ** 2
s = scipy.signal.convolve2d(r, window, mode='same', boundary='symm')
return s.astype(np.uint8)
def convert_3d(r):
s_dsplit = []
for d in range(r.shape[2]):
rr = r[:, :, d]
ss = convert_2d(rr)
s_dsplit.append(ss)
s = np.dstack(s_dsplit)
return s
def add_salt_noise(img):
rows, cols, dims = img.shape
R = np.mat(img[:, :, 0])
G = np.mat(img[:, :, 1])
B = np.mat(img[:, :, 2])
Grey_sp = R * 0.299 + G * 0.587 + B * 0.114
Grey_gs = R * 0.299 + G * 0.587 + B * 0.114
snr = 0.9
noise_num = int((1 - snr) * rows * cols)
for i in range(noise_num):
rand_x = random.randint(0, rows - 1)
rand_y = random.randint(0, cols - 1)
if random.randint(0, 1) == 0:
Grey_sp[rand_x, rand_y] = 0
else:
Grey_sp[rand_x, rand_y] = 255
Grey_gs = Grey_gs + np.random.normal(0, 48, Grey_gs.shape)
Grey_gs = Grey_gs - np.full(Grey_gs.shape, np.min(Grey_gs))
Grey_gs = Grey_gs * 255 / np.max(Grey_gs)
Grey_gs = Grey_gs.astype(np.uint8)
Grey_sp_mf = scipy.ndimage.median_filter(Grey_sp, (7, 7))
Grey_gs_mf = scipy.ndimage.median_filter(Grey_gs, (8, 8))
Grey_sp_me = convert_2d(Grey_sp)
Grey_gs_me = convert_2d(Grey_gs)
plt.subplot(321)
plt.title('加入椒盐噪声',fontproperties=font_set)
plt.imshow(Grey_sp, cmap='gray')
plt.subplot(322)
plt.title('加入高斯噪声',fontproperties=font_set)
plt.imshow(Grey_gs, cmap='gray')
plt.subplot(323)
plt.title('中值滤波去椒盐噪声(8*8)',fontproperties=font_set)
plt.imshow(Grey_sp_mf, cmap='gray')
plt.subplot(324)
plt.title('中值滤波去高斯噪声(8*8)',fontproperties=font_set)
plt.imshow(Grey_gs_mf, cmap='gray')
plt.subplot(325)
plt.title('均值滤波去椒盐噪声',fontproperties=font_set)
plt.imshow(Grey_sp_me, cmap='gray')
plt.subplot(326)
plt.title('均值滤波去高斯噪声',fontproperties=font_set)
plt.imshow(Grey_gs_me, cmap='gray')
plt.show()
实验结果:
(1):
(2):
(3):
实验结果分析:
- 均值滤波器操作简单,“无差别”模糊了图像各部分;中值滤波器能够很好的滤除“椒盐”噪声。椒盐噪声是在图像上随机出现的孤立点,根据中值滤波器的原理,使用邻域像素的中值代替原像素,能够有效的消除这些孤立的噪声点。
- 在不同光照成像,不同阴影亮度图像处理对比下,发现,和均值滤波器相比,中值滤波在消除噪声的同时,还能在很大程度保护图像的细节,不会造成很大的模糊。
四、频率域滤波器
由前一章的学习得,用频率域技术可以有效分析并滤除周期噪声。这种技术的基础是傅里叶变换下,周期噪声在对应于周期干扰
的频率处,以集中的能量脉冲形式出现。可以用一个选择性滤波器分离出噪声。
在上一章傅里叶变换计算中,我们已经知道了如何将图像转换到频率域,以及如何将频率域图像通过傅里叶逆变换转换回图像,
这样一来,可以利用空域图像与频谱之间的对应关系,尝试将空域卷积滤波变换为频域滤波,而后再将频域滤波处理后的图像反变
回空间域,从而达到图像增强的目的,这样做的一个最主要的吸引力再域频率域滤波具有直观性的特点。
频域滤波主要分为四个步骤:
- 计算源图像的傅里叶变换结果
- 选择并计算滤波器
- 将1得到的结果和2的结果相乘
- 对3的结果进行逆傅里叶变换
本次选择的滤波器有 1.理想低通 ;2.布特沃斯低通 ;3.高斯低通;(这三个起平滑作用)
利用 HP+LP=1可计算高频滤波器:4.理想高通 ;5.布特沃斯高通 ;6.高斯高通 (这三个起锐化作用)
实验:
1.傅里叶变换:
# 计算最优尺寸
nrows = cv2.getOptimalDFTSize(rows)
ncols = cv2.getOptimalDFTSize(cols)
# 根据新尺寸,建立新变换图像
nimg = np.zeros((nrows, ncols))
nimg[:rows,:cols] = img
# 得到的fft_mat有2个通道,实部和虚部
fft_mat = cv2.dft(np.float32(nimg), flags = cv2.DFT_COMPLEX_OUTPUT)
# 反换位,低频部分移到中间,高频部分移到四周
fft_mat = np.fft.fftshift(fft_mat)
2.选择D(u,v)
def fft_distances(m, n):
u = np.array([i - m/2 for i in range(m)], dtype=np.float32)
v = np.array([i - n/2 for i in range(n)], dtype=np.float32)
ret = np.ones((m, n))
for i in range(m):
for j in range(n):
ret[i][j] = np.sqrt(u[i]*u[i] + v[j]*v[j])
u = np.array([i if i<=m/2 else m-i for i in range(m)], dtype=np.float32)
v = np.array([i if i<=m/2 else m-i for i in range(m)], dtype=np.float32)
return ret
3.滤波器:
(1)理想低通滤波器与理想高通滤波器
理想低通滤波器:
python实现:
# 理想低通滤波器
filter_mat = np.zeros((nrows, ncols ,2), np.float32)
# 将filter_mat中以(ncols/2, nrows/2)为圆心、d0为半径的圆内的值设置为1
cv2.circle(filter_mat, (np.int(ncols/2), np.int(nrows/2)) , d0, (1,1,1), -1)
效果:
先修改一下滤波器半径为(ncols/3, nrows/3)后效果:
再修改为 (ncols/4, nrows/4)后效果:
实验总结:随着滤波器半径的增大,滤除的功率越来越少;随着被滤除的高频内容的数量的减少,图像的纹理越来越得到改善,同时振铃现象也很明显,失真越来越重给,物体的边界也被加粗。
现在再来对比一下同情况下的理想高通滤波器:
img2 = ifft((1 - change_filter(1)) * fft_mat)#理想高通滤波器
滤波器半径为(ncols/2, nrows/2)时的效果:
滤波器半径为(ncols/3, nrows/3)时的效果:
滤波器半径为(ncols/4, nrows/4)时的效果:
实验总结:上下对比可以发现,随着滤波器半径增大,物体的边缘细节也越来越明显,边缘失真也越来越严重,振铃现象也在加重。
较小物体和线条几乎显示为纯白色(卷积效果)。
(2)布特沃斯低通与布特沃斯高通
布特沃斯低通:
python实现:
#布特沃斯低通
n = 2 # 2阶
filter_mat = None
duv = fft_distances(*fft_mat.shape[:2])
filter_mat = 1 / (1+ np.power(duv/d0, 2*n))
filter_mat = cv2.merge((filter_mat, filter_mat))
首先是一阶布特沃斯低通:n=1,效果:
二阶布特沃斯低通:n=2,效果:
三阶布特沃斯低通:n=3,效果:
实验总结:最直观感受是随着阶数的增加,图像越来越模糊,失真越来越严重,振铃越来越明显,与理想低通滤波器处理的效果对比,图像模糊没有那么剧烈,物体界限区别比较不那么“刺眼”,比较平滑。
现在再来对比一下同情况下的布特沃斯高通滤波器:
python实现:
img2 = ifft((1 - change_filter(2)) * fft_mat) # 布特沃斯高通
首先是一阶布特沃斯高通:n=1,效果:
二阶布特沃斯高通:n=2,效果:
三阶布特沃斯高通:n=3,效果:
实验总结:随着阶数增大,细节会更明显一些。与理想高通滤波器对比,处理效果平滑。
(3)高斯低通滤波器与高斯高通滤波器
高斯低通滤波器:
python实现:
#高斯低通滤波器
filter_mat = None
duv = fft_distances(*fft_mat.shape[:2])
filter_mat = np.exp(-(duv*duv) / (2*d0*d0))
filter_mat = cv2.merge((filter_mat, filter_mat))
当D0=10时效果:
当D0=20时效果:
当D0=40时效果:
实验总结:首先是随着D0的变化没有振铃现象,图像比较清晰,在同截至频率下,平滑效果不如二阶布特沃斯低通滤波器,对噪声的模糊处理对比前两种低通滤波目测有比较好的表现。适合用在精度比较高的场合。
现在再来对比一下同情况下的高斯高通滤波器:
python实现:
img2 = ifft((1 - change_filter(3)) * fft_mat) # 高斯高通
当D0=10时效果:
当D0=20时效果:
当D0=40时效果:
实验总结:随着D0的变化没有振铃现象,典型的暗色调明显,图像细节提取比较清晰,对比前两种高通滤波器即使是微小物体和线条也会更清晰一点,适合用在精度比较高的场合。
五、最小均方误差(维纳)滤波
对于运动引起的图像模糊,最简单的方法是直接做逆滤波,但是逆滤波对加性噪声特别敏感,使得恢复的图像几乎不可用(通过实验可知)。经过研究提出了一些改进方法,其中之一就是最小均方差滤波。
最小均方差(维纳)滤波用来去除含有噪声的模糊图像,其目标是找到未污染图像的一个估计,使它们之间的均方差最小,可以去除噪声,同时清晰化模糊图像。
目标是找出一个未污染的图像的一个估计,使得它们之间的均方误差最小。
维纳滤波的实质就是:一个复数量与其共轭的乘积等于该复数量幅度的平方。
通过实验来对比一下维纳滤波对逆滤波性能的改善:
python实现:
# 仿真运动模糊
def motion_process(image_size,motion_angle):
PSF = np.zeros(image_size)
print(image_size)
center_position=(image_size[0]-1)/2
print(center_position)
slope_tan=math.tan(motion_angle*math.pi/180)
slope_cot=1/slope_tan
if slope_tan<=1:
for i in range(15):
offset=round(i*slope_tan) #((center_position-i)*slope_tan)
PSF[int(center_position+offset),int(center_position-offset)]=1
return PSF / PSF.sum() #对点扩散函数进行归一化亮度
else:
for i in range(15):
offset=round(i*slope_cot)
PSF[int(center_position-offset),int(center_position+offset)]=1
return PSF / PSF.sum()
#对图片进行运动模糊
def make_blurred(input, PSF, eps):
input_fft = fft.fft2(input)# 进行二维数组的傅里叶变换
PSF_fft = fft.fft2(PSF)+ eps
blurred = fft.ifft2(input_fft * PSF_fft)
blurred = np.abs(fft.fftshift(blurred))
return blurred
def inverse(input, PSF, eps): # 逆滤波
input_fft = fft.fft2(input)
PSF_fft = fft.fft2(PSF) + eps #噪声功率,这是已知的,考虑epsilon
result = fft.ifft2(input_fft / PSF_fft) #计算F(u,v)的傅里叶反变换
result = np.abs(fft.fftshift(result))
return result
def wiener(input,PSF,eps,K=0.01): #维纳滤波,K=0.01
input_fft=fft.fft2(input)
PSF_fft=fft.fft2(PSF) +eps
PSF_fft_1=np.conj(PSF_fft) /(np.abs(PSF_fft)**2 + K)
result=fft.ifft2(input_fft * PSF_fft_1)
result=np.abs(fft.fftshift(result))
return result
原图像:
对比处理:k=0.01时
k=0.05时:
k=0.1时:
实验总结:非常明显,与直接逆滤波相比,当有运动噪声和随机噪声同时存在维纳滤波的处理效果优势明显,对噪声的过滤性能优越。当只有运动噪声时,如果k只选取不当,维纳滤波的优越性难以体现。故此,可以发现维纳滤波的缺点就是难以靠数学分析发现最合适的k值,需要手工交互选取合适的k值,这个可以通过约束最小二乘方滤波。
利用python做数字图像处理时,一定要先安装各种图像处理的包,在不同的python版本偶尔会有些许小区别;函数书写前后一致,保持在全英文输入法下输入不要混用中英文标点,命名用英语,汉语大概率报错。(自己的基本功需要加固,不然编程翻车很崩溃!)