如何使用Python去除图像中的椒盐噪声?

3
我尝试实现了以下算法,但生成的图像看起来和之前一样。
步骤1:读取噪声图片。
步骤2:选择大小为3x3的二维窗口,以处理像素点的中心元素为准。假设正在处理的像素为Pij。
步骤3:如果Pij是未受损的像素(即0 < Pij < 255),则保持其值不变。
步骤4:如果Pij = 0或Pij = 255,则Pij是一个受损的像素。
步骤5:如果所选窗口中有3/4或更多的像素是噪声,则将窗口大小增加到5x5。
步骤6:如果所选窗口中的所有元素都是0或255,则用窗口中元素的平均值替换Pij,否则转到步骤7。
步骤7:从所选窗口中消除0和255,并找到剩余元素的中位数值。用中位数值替换Pij。
步骤8:重复步骤2至6,直到整个图像的所有像素都被处理完毕。
这是我的代码,请提出改进意见。
import Image

im=Image.open("no.jpg")
im = im.convert('L')

for i in range(2,im.size[0]-2):
    for j in range(2,im.size[1]-2):
        b=[]
        if im.getpixel((i,j))>0 and im.getpixel((i,j))<255:
            pass
        elif im.getpixel((i,j))==0 or im.getpixel((i,j))==255:
            c=0
            for p in range(i-1,i+2):
                for q in range(j-1,j+2):
                    if im.getpixel((p,q))==0 or im.getpixel((p,q))==255: 
                        c=c+1
            if c>6:
                c=0
                for p in range(i-2,i+3):
                    for q in range(j-2,j+3):
                        b.append(im.getpixel((p,q)))
                        if im.getpixel((p,q))==0 or im.getpixel((p,q))==255:
                            c=c+1
                if c==25:
                    a=sum(b)/25
                    print a
                    im.putpixel((i,j),a)
                else:
                    p=[]
                    for t in b:
                        if t not in (0,255):
                            p.append(t)
                    p.sort()
                    im.putpixel((i,j),p[len(p)/2])
            else:
                b1=[]
                for p in range(i-1,i+2):
                    for q in range(j-1,j+2):
                        b1.append(im.getpixel((p,q)))
                im.putpixel((i,j),sum(b1)/9)

im.save("nonoise.jpg")   

你是通过视觉检查还是图像差异来确定这两个图像是否相同的?除了几个像素之外,它们可能看起来很相似。查看您的代码的一个问题是,无论像素是0还是255,您都会将其附加到临时数组(b和b1)中。如果您只想要有效像素的中位数,则需要在附加之前进行额外的测试。其次,您正在计算类似于平均值而不是中位数(numpy.median)。 - Paul
3个回答

7

您应该使用中值滤波器,它易于实现且非常适用于椒盐噪声。


3

正如Olivier所建议的,中值滤波提供了最好的结果。

以下是我为图像添加椒盐噪声而生成的代码。此代码适用于带有OpenCV 3.0.0的Python:

import numpy as np
import cv2

img = cv2.imread('3.jpg', 1)
row,col,ch = img.shape
p = 0.5
a = 0.009
noisy = img

  # Salt mode
num_salt = np.ceil(a * img.size * p)
coords = [np.random.randint(0, i - 1, int(num_salt))
          for i in img.shape]
noisy[coords] = 1

  # Pepper mode
num_pepper = np.ceil(a * img.size * (1. - p))
coords = [np.random.randint(0, i - 1, int(num_pepper))
          for i in img.shape]
noisy[coords] = 0

cv2.imshow('noisy', noisy)

以下是使用中值滤波器的代码:

median_blur= cv2.medianBlur(noisy, 3)
cv2.imshow('median_blur', median_blur)  

cv2.waitKey()
cv2.destroyAllWindows()

可以根据需要修改用于模糊噪声图像的窗口。


0
你的输入图像是什么样子的?你的算法假设只有像素值0和255是噪声。如果你的噪点像素实际上具有其他值,那么你的算法将不会执行任何操作,你可能会看到输出与输入完全相同的结果。

尽管我有一些像素值为0和255,但输出图像与输入图像相同。 - user3395151

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接