改进的自适应中值滤波算法 去除椒盐噪声 python 代码实现

完整代码可以在 我的AI学习笔记 - github 中获取

原理

传统的中值滤波算法在椒盐噪声的去除领域有着比较广泛的应用,其具有较强的噪点鉴别和恢复能力,也有比较低的时间复杂度:其基本思想是采用像素点周围邻接的若干像素点的中值来代替被污染的像素点;但也存在一定的缺陷,随着图像被污染程度的加深,此方法恢复的图像细节模糊、边缘损失也会越严重。

中值滤波的思想就是比较一定领域内的像素值的大小,取出其中值作为这个领域的中心像素新的值。假设对一定领域内的所有像素从小到大进行排序,如果存在孤立的噪声点,比如椒盐噪声(椒噪声——较小的灰度值,呈现的效果是小黑点;盐噪声——较大的灰度值,呈现的效果是小白点),那么从小到大排序的这个数组中,那些孤立的噪声一定会分布在两边(要么很小,要么很大),这样子取出的中值点可以很好地保留像素信息,而滤除了噪声点的影响。
中值滤波器受滤波窗口大小影响较大,用于消除噪声和保护图像细节,两者会存在冲突。如果窗口较小,则能较好地保护图像中的一些细节信息,但对噪声的过滤效果就会打折扣;反之,如果窗口尺寸较大则会有较好的噪声过滤效果,但也会对图像造成一定的模糊效果,从而丢失一部分细节信息。

此处采用改进的自适应中值滤波算法进行图像恢复:

  1. 根据图像处理的空间相关性原则,采用自适应的方法选择不同的滑动窗口大小;
    在这里插入图片描述
  2. 在算法中单滤波窗口大小达到最大值时,采用均值滤波;

代码实现

def get_window(res_img,noise_mask,sc,i,j,k):
    listx = []
                 
    if i-sc >= 0:
        starti = i-sc 
    else:
        starti = 0
    if j+1 <= res_img.shape[1]-1 and noise_mask[0,j+1,k] !=0:
        listx.append(res_img[0,j+1,k])
    if j-1 >=0 and noise_mask[0,j-1,k] !=0:
        listx.append(res_img[0,j-1,k])
                    
    if i+sc <= res_img.shape[0]-1:
        endi = i+sc
    else:
        endi = res_img.shape[0]-1
    if j+1 <= res_img.shape[1]-1 and noise_mask[endi,j+1,k] !=0:
        listx.append(res_img[endi,j+1,k])
    if j-1 >=0 and noise_mask[endi,j-1,k] !=0:
        listx.append(res_img[endi,j-1,k])
                        
    if j+sc <= res_img.shape[1]-1:
        endj = j+sc
    else:
        endj = res_img.shape[1]-1
    if i+1 <= res_img.shape[0]-1 and noise_mask[i+1,endj,k] !=0:
        listx.append(res_img[i+1,endj,k])
    if i-1 >=0 and noise_mask[i-1,endj,k] !=0:
        listx.append(res_img[i-1,endj,k])
                    
    if j-sc >= 0:
        startj = j-sc
    else:
        startj = 0
    if i+1 <= res_img.shape[0]-1 and noise_mask[i+1,0,k] !=0:
        listx.append(res_img[i+1,0,k])
    if i-1 >=0 and noise_mask[i-1,0,k] !=0:
        listx.append(res_img[i-1,0,k])
                                        
    for m in range(starti,endi+1):
        for n in range(startj,endj+1):
            if noise_mask[m,n,k] != 0:
                listx.append(res_img[m,n,k])
    listx.sort()
    return listx

def get_window_small(res_img,noise_mask,i,j,k):
    listx = []
    sc = 1             
    if i-sc >= 0 and noise_mask[i-1,j,k]!=0:
        listx.append(res_img[i-1,j,k])

    if i+sc <= res_img.shape[0]-1 and noise_mask[i+1,j,k]!=0:
        listx.append(res_img[i+1,j,k])
                        
    if j+sc <= res_img.shape[1]-1 and noise_mask[i,j+1,k]!=0:
        listx.append(res_img[i,j+1,k])
                    
    if j-sc >= 0 and noise_mask[i,j-1,k]!=0:
        listx.append(res_img[i,j-1,k])
    listx.sort()
    return listx

def restore_image(noise_img, size=4):
    """
    使用 你最擅长的算法模型 进行图像恢复。
    :param noise_img: 一个受损的图像
    :param size: 输入区域半径,长宽是以 size*size 方形区域获取区域, 默认是 4
    :return: res_img 恢复后的图片,图像矩阵值 0-1 之间,数据类型为 np.array,
            数据类型对象 (dtype): np.double, 图像形状:(height,width,channel), 通道(channel) 顺序为RGB
    """
    # 恢复图片初始化,首先 copy 受损图片,然后预测噪声点的座标后作为返回值。
    res_img = np.copy(noise_img)

    # 获取噪声图像
    noise_mask = get_noise_mask(noise_img)

    for i in range(noise_mask.shape[0]):
        for j in range(noise_mask.shape[1]):
            for k in range(noise_mask.shape[2]):
                if noise_mask[i,j,k] == 0:
                    sc = 1
                    listx = get_window_small(res_img,noise_mask,i,j,k)
                    if len(listx) != 0:
                        res_img[i,j,k] = listx[len(listx)//2]
                    else:
                        while(len(listx) == 0):
                            listx = get_window(res_img,noise_mask,sc,i,j,k)
                            sc = sc+1
                        if sc > 4:
                            res_img[i,j,k] = np.mean(listx)
                        else:
                            res_img[i,j,k] = listx[len(listx)//2]

    return res_img

恢复效果:

原始图片
在这里插入图片描述
添加噪点
在这里插入图片描述
恢复后
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章