python3-scikit-image平滑去噪

发布时间:2021-09-29 00:24:51编辑:run阅读(4939)

    scikit-image库还在图像复原模块中提供了一组非线性滤波器。

    双边滤波器是一种边缘识别的平滑滤波器,对于这种滤波器,中心像素被设置为它的某些邻域像素值的加权平均值,而这些邻域像素值的亮度与中心像素的大致相似。使用scikit-image包中的双边滤波器实现图像去噪。


    生成一幅噪声图像

    from skimage import data, img_as_float,img_as_ubyte, exposure, io, color
    from skimage import color, data, restoration
    from skimage.util import random_noise
    import matplotlib.pylab as pylab
    
    pylab.rcParams['font.sans-serif'] = ['KaiTi']
    pylab.rcParams['axes.unicode_minus'] = False
    def plot_image(image, title=''):
        pylab.title(title, size=20)
        pylab.imshow(image)
        pylab.axis('off')
    im = color.rgb2gray(img_as_float(io.imread(r'D:\image_processing\image4\aa.jpg')))
    pylab.figure(figsize=(20, 15))
    pylab.subplot(1, 2, 1)
    plot_image(im, '原始图像')
    sigma = 0.155
    noisy = random_noise(im, var=sigma**2)
    pylab.subplot(1, 2, 2)
    plot_image(noisy, '噪声图像')
    pylab.show()

    image.png


    使用双边滤波器对上面的噪声图像去噪,采用不同的参数值。

    from skimage import data, img_as_float,img_as_ubyte, exposure, io, color
    from skimage import color, data, restoration
    from skimage.restoration import denoise_bilateral
    from skimage.util import random_noise
    import matplotlib.pylab as pylab
    
    pylab.rcParams['font.sans-serif'] = ['KaiTi']
    pylab.rcParams['axes.unicode_minus'] = False
    def plot_image(image, title=''):
        pylab.title(title, size=25)
        pylab.imshow(image)
        pylab.axis('off')
    im = color.rgb2gray(img_as_float(io.imread(r'D:\image_processing\image4\aa.jpg')))
    pylab.figure(figsize=(20, 15))
    pylab.subplot(1, 2, 1)
    plot_image(im, '原始图像')
    sigma = 0.155
    noisy = random_noise(im, var=sigma**2)
    pylab.figure(figsize=(20, 15))
    i = 1
    for sigma_sp in [5, 10, 20]:
        for sigma_col in [0.1, 0.25, 5]:
            pylab.subplot(3, 3, i)
            pylab.imshow(denoise_bilateral(noisy, sigma_color=sigma_col,
            sigma_spatial=sigma_sp, multichannel=False))
            pylab.title(r'$\sigma_r=$' + str(sigma_col) + r', $\sigma_s=$' + str(sigma_sp), size=20)
            i += 1
    pylab.show()

    image.png

    可以看到,如果标准差越大,那么图像的噪声越小,但模糊程度越高。



    非局部均值滤波器实际上是一种保留纹理的非线性去噪算法,在该算法中,对于任意给定的像素,仅使用与感兴趣的像素具有相似局部邻域像素的加权平均值来设置它的值。换言之,就是将以其他像素为中心的小斑块与以感兴趣像素为中心的斑块进行比较。通过使用非局部均值滤波器对图像去噪来演示算法。函数的h参数控制斑块权重的衰减,它是斑块之间距离的函数。如果h很大,它允许不同的斑块之间有更多的平滑。

    from skimage.io import imread
    from skimage import data, img_as_float
    from skimage.restoration import denoise_bilateral, denoise_nl_means, estimate_sigma
    import matplotlib.pylab as pylab
    import numpy as np
    from skimage import metrics
    
    pylab.rcParams['font.sans-serif'] = ['KaiTi']
    pylab.rcParams['axes.unicode_minus'] = False
    def plot_image_axes(image, axes, title):
        axes.imshow(image)
        axes.axis('off')
        axes.set_title(title, size=25)
    parrot = img_as_float(imread(r'D:\image_processing\image4\aa.jpg'))
    sigma = 0.25
    noisy = parrot + sigma * np.random.standard_normal(parrot.shape)
    noisy = np.clip(noisy, 0, 1)
    sigma_est = np.mean(estimate_sigma(noisy, multichannel=True))
    patch_kw = dict(patch_size=5, patch_distance=6, multichannel=True)
    denoise = denoise_nl_means(noisy, h=1.15 * sigma_est, fast_mode=False, **patch_kw)
    denoise_fast = denoise_nl_means(noisy, h=0.8 * sigma_est, fast_mode=True, **patch_kw)
    fig, axes = pylab.subplots(nrows=2, ncols=2, figsize=(15, 12), sharex=True, sharey=True)
    plot_image_axes(noisy, axes[0, 0], '噪声图像')
    plot_image_axes(denoise, axes[0, 1], '非局部均值(慢)')
    plot_image_axes(parrot, axes[1, 0], '原始图像(无噪声)')
    plot_image_axes(denoise_fast, axes[1, 1], '非局部均值(快)')
    fig.tight_layout()
    psnr_noisy = metrics.peak_signal_noise_ratio(parrot, noisy)
    psnr = metrics.peak_signal_noise_ratio(parrot, denoise.astype(np.float64))
    psnr_fast = metrics.peak_signal_noise_ratio(parrot, denoise_fast.astype(np.float64))
    pylab.show()

    image.png

    可以看到,慢版本的算法比快版本的峰值信噪比更好,这是一种权衡。两种算法输出图像的PSNR都比噪声图像高得多。

关键字