Python实现图像的椒盐噪声添加和基础的平滑处理(均值滤波与中值滤波)

均值滤波与中值滤波是最常见的两种平滑的方式,尤其是中值滤波能起到强大的降噪效果。

本文内容分为三部分:
1.实现添加图片的椒盐噪声
2.实现调用内置函数进行均值和中值滤波
3.自编函数深刻理解均值和中值滤波

1.何为椒盐噪声?如何添加椒盐噪声?

首先我们知道在图像当中的噪声实际上就是在图像中捣乱的像素点。

懂了之后椒盐噪声就很好理解了。
其实椒盐噪声(pepper and salt noise),就是字面意思。好像是黑胡椒和白盐的噪声. 具体来讲如下图所示:
左侧为原图 右侧为添加了4%椒盐噪声后的图片。
在这里插入图片描述
放大了看上面有黑色和白色的小点。我们只要在原有的图像中把相应的像素点随机改为黑色和白色的就好了.实现方法如下:

import cv2
import random
def pepper_and_salt(img,percentage):
    num=int(percentage*img.shape[0]*img.shape[1])#  椒盐噪声点数量
    random.randint(0, img.shape[0])
    img2=img.copy()
    for i in range(num):
        X=random.randint(0,img2.shape[0]-1)#从0到图像长度之间的一个随机整数,因为是闭区间所以-1
        Y=random.randint(0,img2.shape[1]-1)
        if random.randint(0,1) ==0: #黑白色概率55开
            img2[X,Y] = (255,255,255)#白色
        else:
            img2[X,Y] =(0,0,0)#黑色
    return img2
img=cv2.imread("lena.tiff")
img2 = pepper_and_salt(img,0.04)#百分之4的椒盐噪音
cv2.imshow("lena",img)
cv2.imshow("lena_pepper_and_salt",img2)
cv2.waitKey(0)

2.实现图像均值滤波和中值滤波

二者的原理都十分简单,常见的方法中

均值就是把一个像素点九宫格(取决于你的输入)内所有点的rgb值加在一起再除以9,也就是取九宫格九个格子的平均值,来覆盖原有的rgb值。而中值滤波则就是取九个格子的中位数来覆盖原有的rgb值。

当然不一定是九宫格,这取决于你的输入,反正是一个你输入数字的n*n宫格的平均值(均值滤波) 或 中位数 (中值)

实现代码非常简单,如下所示:

img_averaging=cv2.blur(img2,(3,3)) #均值滤波
img_median = cv2.medianBlur(img2,3) #中值滤波

cv2.imshow("lena_averaging",img_averaging)
cv2.imshow("lena_median",img_median)
cv2.waitKey(0)

这里面要注意的就是中值滤波中的输入不能为偶数,你想你一个偶数取中位数不就有小数点了吗?或者是去前面和后面,就不准确了。所有只能是奇数

效果如下
在这里插入图片描述
你可以明显的看出来,均值滤波的效果不是十分明显,而中值滤波简直神了,几乎还原了原图。

到了这里,题目的要求就已经完成了。

3、自行实现两者

首先来说,一般来说如果有内置的函数尽量使用内置的函数,这样运行速度快,相对来讲兼容性要好而且方便。但是这里只是提供一个大致的编程思路。

话不多说了,因为逻辑上十分简单,所以实现起来也不困难。
直接上代码:
1.均值滤波

def averaging_filter(img,tuple_reform):
    img2=img.copy()
    X=img2.shape[0]
    Y=img2.shape[1]
    shift=int((tuple_reform[0]+tuple_reform[1]-2)/2)
    for x in range(shift,X-shift):
        for y in range(shift,Y-shift):
            pixel_r=0
            pixel_g=0
            pixel_b=0

            for i in range(tuple_reform[0]): #方位上取前3个的维度的
                for j in range(tuple_reform[1]):
                    pixel_r+=int(img[x+i-shift,y+j-shift,0])
                    pixel_g+=int(img[x+i-shift,y+j-shift,1])
                    pixel_b+=int(img[x+i-shift,y+j-shift,2])

            num=tuple_reform[0]*tuple_reform[1]
            img2[x,y,0] = int(pixel_r/num)
            img2[x,y,1] = int(pixel_g/num)
            img2[x,y,2] = int(pixel_b/num)
            #该像素点等于9宫格内所有相加取平均而成,
    return img2

2.中值滤波

def median_filter(img,median):
    img2 = img.copy()
    X = img2.shape[0]
    Y = img2.shape[1]
    edge = int((median) -1/ 2) # 每条边上做这么多次
    shift = int(edge / 2)  # 计算位置的偏移量
    edge+=1
    for x in range(shift, X - shift):
        for y in range(shift, Y - shift):
            List_r=[] #收集五个点的rgb值
            List_g=[]
            List_b=[]
            for e in range(2): #两种情况为0对x加减,为1对y加减
                for i in range(edge):  # 方位上取前3个的维度的
                    if e == 0:
                        List_r.append(int(img2[x + i - shift, y, 0]))
                        List_g.append(int(img2[x + i - shift, y, 1]))
                        List_b.append(int(img2[x + i - shift, y, 2]))
                    else:
                        List_r.append(int(img2[x, y + i - shift, 0]))
                        List_g.append(int(img2[x, y + i - shift, 1]))
                        List_b.append(int(img2[x, y + i - shift, 2]))
            List_r.remove(img2[x,y,0]) #消除重复元素
            List_g.remove(img2[x, y, 1])
            List_b.remove(img2[x, y, 2])

            img2[x, y, 0] = np.median(List_r)
            img2[x, y, 1] = np.median(List_g)
            img2[x, y, 2] = np.median(List_b)
    return img2

提示:我所实现的中值滤波方式与正常的九宫格式不同,而是一个十字型阵列,以原来的那个像素点为十字交叉点,同样也是取中值。

且我实现的方法从算法的角度上不好,因为时间复杂度很高,再加上实现中值滤波时采用了每个像素点都要创建列表进行收集。

效果如下:

其实刚才有的小伙伴就以及想到了,我那样子去进行九宫格似的取中位数和平均那周围的点怎么办呢?
常见的处理办法有三种:
1.不做处理。就像我这里一样,因为边界很小,不影响大局,但是边上还是会存在一些噪声
2.边上的rgb值取0.这个方法会使得边上出现一个黑框
3.滤波后,边框上的点的rgb值等于 距离边框上每个像素点最近的像素点的rgb值.应该就是内置函数的操作,边上就不会有噪声

  • 21
    点赞
  • 74
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
平滑滤波、均值滤波和锐化滤波都是数字图像处理中常用的滤波方法。 1. 平滑滤波 平滑滤波是一种常用的图像滤波方法,它可以去除图像中的噪声,使图像变得更加平滑平滑滤波的基本思想是用一个模板对图像进行卷积,将每个像素的值替换为该像素周围像素的平均值。常用的平滑滤波方法有均值滤波中值滤波等。 2. 均值滤波 均值滤波是一种最简单的平滑滤波方法,它的基本思想是用一个固定大小的模板对图像进行卷积,将每个像素的值替换为该像素周围像素的平均值。均值滤波可以有效地去除高斯噪声和椒盐噪声,但是会使图像变得模糊。 下面是一个3x3的均值滤波器的示例代码: ```python import cv2 import numpy as np img = cv2.imread('image.jpg') kernel = np.ones((3,3),np.float32)/9 dst = cv2.filter2D(img,-1,kernel) cv2.imshow('Original', img) cv2.imshow('Averaging', dst) cv2.waitKey(0) cv2.destroyAllWindows() ``` 3. 锐化滤波 锐化滤波是一种常用的图像增强方法,它可以使图像变得更加清晰。锐化滤波的基本思想是用一个模板对图像进行卷积,将每个像素的值替换为该像素周围像素的加权和。常用的锐化滤波方法有拉普拉斯滤波、Sobel滤波等。 下面是一个拉普拉斯滤波器的示例代码: ```python import cv2 import numpy as np img = cv2.imread('image.jpg') kernel = np.array([[0,-1,0],[-1,5,-1],[0,-1,0]],np.float32) dst = cv2.filter2D(img,-1,kernel) cv2.imshow('Original', img) cv2.imshow('Sharpened', dst) cv2.waitKey(0) cv2.destroyAllWindows() ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值