K nearest neighbor averaging
基本原理
编程实现
导入相应的库文件
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import skimage.util as util
from skimage import data, img_as_float
from skimage.metrics import structural_similarity as ssim
from skimage.metrics import mean_squared_error as MSE
from skimage.metrics import peak_signal_noise_ratio as psnr
读取skimage库自带的图像,cameraman,并添加噪声
img = img_as_float(data.camera())
rows, cols = img.shape
#noise_img = util.random_noise(img,mode='gaussian',var=0.05)
img_noise_1 = util.random_noise(img,mode='s&p')
img_noise_2 = util.random_noise(img,mode='gaussian',var = 0.1**2)
本程序添加的噪声类型有两种,高斯 噪声和椒盐噪声
fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(10, 4))
ax = axes.ravel()
ax[0].imshow(img, cmap=plt.cm.gray, vmin=0, vmax=1)
ax[0].set_title('Original image')
ax[0].axis('off')
ax[1].imshow(img_noise_1, cmap=plt.cm.gray, vmin=0, vmax=1)
ax[1].set_title('Image with s&p noise')
ax[1].axis('off')
ax[2].imshow(img_noise_2, cmap=plt.cm.gray, vmin=0, vmax=1)
ax[2].set_title('Image with gaussian noise')
ax[2].axis('off')
定义函数实现k个零点平均
def K_nearest_average(noise_img,windows_size=3,k_num = 6):
"""
# 本函数旨在实现灰度最邻近的K个邻点平均
input:
------------------------------------
noise_img: 输入的含噪声图像
windows_size: 窗口的大小
k_num: 灰度值最接近的K个邻点的平均灰度值来代替中心的灰度值
output:
------------------------------------
img_out: 最邻近的K个邻点平均去噪图像
"""
rows, cols = noise_img.shape
half_size = windows_size//2
ndarray=np.pad(noise_img,(half_size,half_size),'constant')#对图像边界进行补零填充
img_out = np.zeros((rows,cols),dtype='double')
for x in range(half_size,rows):
for y in range(half_size,cols):
window = ndarray[x-half_size:x+half_size+1,y-half_size:y+half_size+1]
window_flatten = (window-ndarray[x,y]).reshape(windows_size**2)
temp = np.argsort(np.abs(window_flatten)) #按照与中心点的灰度值的差异值进行排序
img_out[x-1,y-1] = np.average(window_flatten[temp[1:k_num+1]])+ndarray[x,y]
return img_out
对含有椒盐噪声的图像去噪
并通过原图计算MSE、SSIM(结构相似性)、PSNR(峰值信噪比)来衡量图像质量的好坏
img_out1 = K_nearest_average(img_noise_1,3,6)
img_out2 = K_nearest_average(img_noise_1,3,3)
img_out3 = K_nearest_average(img_noise_1,5,12)
mse_noise = MSE(img, img_noise_1)
ssim_noise = ssim(img, img_noise_1,
data_range=img_noise_1.max() - img_noise_1.min())
psnr_noise =psnr(img,img_noise_1)
mse_out1 = MSE(img,img_out1)
ssim_out1 = ssim(img, img_out1,
data_range=img_out1.max() - img_out1.min())
psnr_out1 =psnr(img, img_out1)
mse_out2 = MSE(img,img_out2)
ssim_out2 = ssim(img, img_out2,
data_range=img_out2.max() - img_out2.min())
psnr_out2 =psnr(img, img_out2)
mse_out3 = MSE(img,img_out3)
ssim_out3 = ssim(img, img_out3,
data_range=img_out3.max() - img_out3.min())
psnr_out3 =psnr(img, img_out3)
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(18, 18))
ax = axes.ravel()
label = 'MSE:{:.4f},SSIM:{:.4f},psnr:{:.4f}'
ax[0].imshow(img_noise_1, cmap=plt.cm.gray, vmin=0, vmax=1)
ax[0].set_title('s&p noise image')
ax[0].set_xlabel(label.format(mse_noise, ssim_noise, psnr_noise))
ax[1].imshow(img_out1, cmap=plt.cm.gray, vmin=0, vmax=1)
ax[1].set_title('windows_size =3 ,k_num =6')
ax[1].set_xlabel(label.format(mse_out1, ssim_out1, psnr_out1))
ax[2].imshow(img_out2, cmap=plt.cm.gray, vmin=0, vmax=1)
ax[2].set_title('windows_size =3 ,k_num =3')
ax[2].set_xlabel(label.format(mse_out2, ssim_out2, psnr_out2))
ax[3].imshow(img_out3, cmap=plt.cm.gray, vmin=0, vmax=1)
ax[3].set_title('windows_size =5 ,k_num =12')
ax[3].set_xlabel(label.format(mse_out3, ssim_out3, psnr_out3))
plt.show()
对含有高斯噪声的图像去噪
并通过原图计算MSE、SSIM(结构相似性)、PSNR(峰值信噪比)来衡量图像质量的好坏
img_out4 = K_nearest_average(img_noise_2,3,6)
img_out5 = K_nearest_average(img_noise_2,3,3)
img_out6 = K_nearest_average(img_noise_2,5,12)
mse_noise = MSE(img, img_noise_2)
ssim_noise = ssim(img, img_noise_2,
data_range=img_noise_2.max() - img_noise_2.min())
psnr_noise =psnr(img,img_noise_2)
mse_out4 = MSE(img,img_out4)
ssim_out4 = ssim(img, img_out4,
data_range=img_out4.max() - img_out4.min())
psnr_out4 =psnr(img, img_out4)
mse_out5 = MSE(img,img_out5)
ssim_out5 = ssim(img, img_out5,
data_range=img_out5.max() - img_out5.min())
psnr_out5 =psnr(img, img_out5)
mse_out6 = MSE(img,img_out6)
ssim_out6 = ssim(img, img_out6,
data_range=img_out6.max() - img_out6.min())
psnr_out6 =psnr(img, img_out6)
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(18, 18))
ax = axes.ravel()
label = 'MSE:{:.4f},SSIM:{:.4f},psnr:{:.4f}'
ax[0].imshow(img_noise_2, cmap=plt.cm.gray, vmin=0, vmax=1)
ax[0].set_title('gaussian image')
ax[0].set_xlabel(label.format(mse_noise, ssim_noise, psnr_noise))
ax[1].imshow(img_out4, cmap=plt.cm.gray, vmin=0, vmax=1)
ax[1].set_title('windows_size =3 ,k_num =6')
ax[1].set_xlabel(label.format(mse_out4, ssim_out4, psnr_out4))
ax[2].imshow(img_out5, cmap=plt.cm.gray, vmin=0, vmax=1)
ax[2].set_title('windows_size =3 ,k_num =3')
ax[2].set_xlabel(label.format(mse_out5, ssim_out5, psnr_out5))
ax[3].imshow(img_out6, cmap=plt.cm.gray, vmin=0, vmax=1)
ax[3].set_title('windows_size =5 ,k_num =12')
ax[3].set_xlabel(label.format(mse_out6, ssim_out6, psnr_out6))
plt.show()
得出结论
较小的K值使噪声方差降低较少,但保持细节也较好;而较大的K值平滑噪声较好,但也将使图像模糊,对于3×3窗口,取K=6为宜
本人水平有限,欢迎批评指正!