图像处理——中值滤波

本文介绍中值滤波的基本原理,如何通过移动窗口计算像素点的中值来去除椒盐噪声和保持图像边缘清晰。Python代码示例展示了如何使用OpenCV实现中值滤波,以及在实际应用中如何处理彩色和灰度图像的噪声问题。
摘要由CSDN通过智能技术生成

中值滤波

【定义】中值滤波是一种非线性的信号处理方法,所以它是一种非线性滤波器,也是一种统计排序滤波器。它将每一像素点的灰度值设置为该点某邻域窗口内的所有像素点灰度值的中值。
【目的】中值滤波对孤立的噪声像素即椒盐噪声、脉冲噪声具有良好的滤波效果,可以保持图像的边缘特性,不会使图像产生显著的模糊。
【基本原理/思想】中值滤波是把数字图像或数字序列中一点的值用该点的一个邻域中各点值的中值代替,让周围的像素值接近真实值,从而消除孤立的噪声点。举个例子:
在这里插入图片描述【具体操作/流程】

  1. 用一个奇数点的移动窗口,并将模板中心与图中某个像素位置重合;
  2. 读取模板下各对应的像素灰度值/从小到大,从大到小均可;
  3. 选取灰度序列中,中间的一个像素的灰度值;
  4. 将中间值赋给模板中心位置的像素。

CV自带medianBlur函数
dst = cv2.medianBlur(src, ksize)
参数说明:
1.src: 需要滤波的图片;
2.ksize:核大小,必须是比1大的奇数【举个例子:3,5,7…】

也可以自己写median_Blur函数
废话不多说,上菜。。。
【python代码】

import numpy as np
import cv2
from copy import deepcopy
from PIL import Image
from matplotlib import pyplot as plt

#####################噪声图像###########################
def add_salt_noise(img, snr = 0.5):
    SNR = snr           #指定信噪比
    size = img.size     #获取总共像素个数
    #print(type(size))
    noiseSize = int(size * (1 - SNR))
    for i in range(0, noiseSize):
        # 随机获取 某个点
        xi = int(np.random.uniform(0, img.shape[1]))
        xj = int(np.random.uniform(0, img.shape[0]))
        if img.ndim == 2:  #判断是否为2维图像(即灰度图像)
            img[xj, xi] = 0     #设置值为黑点
        elif img.ndim == 3:
            img[xj, xi] = 0     #设置值为黑点,也可以设置为白色255
    return img

#####################中值滤波###########################
def median_Blur(img, filiter_size = 3):  #当输入的图像为彩色图像
    image_copy = np.array(img, copy = True).astype(np.float32)
    processed = np.zeros_like(image_copy)
    middle = int(filiter_size / 2)
    r = np.zeros(filiter_size * filiter_size)
    g = np.zeros(filiter_size * filiter_size)
    b = np.zeros(filiter_size * filiter_size)
    
    for i in range(middle, image_copy.shape[0] - middle):
        for j in range(middle, image_copy.shape[1] - middle):
            count = 0
            #依次取出模板中对应的像素值
            for m in range(i - middle, i + middle +1):
                for n in range(j - middle, j + middle + 1):
                    r[count] = image_copy[m][n][0]
                    g[count] = image_copy[m][n][1]
                    b[count] = image_copy[m][n][2]
                    count += 1
            r.sort()
            g.sort()
            b.sort()
            processed[i][j][0] = r[int(filiter_size*filiter_size/2)]
            processed[i][j][1] = g[int(filiter_size*filiter_size/2)]
            processed[i][j][2] = b[int(filiter_size*filiter_size/2)]
    processed = np.clip(processed, 0, 255).astype(np.uint8)
    return processed

#####################中值滤波###########################
def median_Blur_gray(img, filiter_size = 3):  #当输入的图像为灰度图像
    image_copy = np.array(img, copy = True).astype(np.float32)
    processed = np.zeros_like(image_copy)
    middle = int(filiter_size / 2)
    
    for i in range(middle, image_copy.shape[0] - middle):
        for j in range(middle, image_copy.shape[1] - middle):
            temp = []
            for m in range(i - middle, i + middle +1):
                for n in range(j - middle, j + middle + 1):
                    if m-middle < 0 or m+middle+1 >image_copy.shape[0] or n-middle < 0 or n+middle+1 > image_copy.shape[1]:
                        temp.append(0)
                    else:
                        temp.append(image_copy[m][n])
                    #count += 1
            temp.sort()
            processed[i][j] = temp[(int(filiter_size*filiter_size/2)+1)]
    processed = np.clip(processed, 0, 255).astype(np.uint8)
    return processed

if __name__ == "__main__":
    img = input("Please input name of image:")  #默认是string类型
    img = cv2.imread(img)
    
    #plt.imshow显示cv2.imread读取的图像有色差发蓝的问题
    #重新整合r,g,b
    #img = Image.open(img)
    b, g, r = cv2.split(img)
    src_img = cv2.merge([r, g, b])
    
    img_demo = deepcopy(src_img)
    snr = float(input("Please input signal noise ratio:"))
    img_salt = add_salt_noise(img_demo, snr)
    
    filiter_size = int(input("Please input size of filiter:"))
    median_blur= median_Blur(img_salt, filiter_size)
    
    plt.figure("Image processing---MedianBlur")           #图像窗口名称
    plt.subplot(1, 3, 1)
    plt.imshow(src_img)
    plt.axis('off')         #关掉坐标轴
    plt.title("src_img")
    
    plt.subplot(1, 3, 2)
    plt.imshow(img_salt)
    plt.axis('off')         #关掉坐标轴
    plt.title("img_salt")
    
    plt.subplot(1, 3, 3)
    plt.imshow(median_blur)
    plt.axis('off')         #关掉坐标轴
    plt.title("median_blur")
    
    plt.tight_layout()  # 调整整体空白
    plt.subplots_adjust(left=None, bottom=None, right=None, top=None,
                wspace=None, hspace=None)  # 调整子图间距
    plt.savefig("reult.png", dpi=1000)
    plt.show()

运行过程:

Please input name of image: whitetulip.jpg
Please input signal noise ratio: 0.99
Please input size of filiter: 3

结果显示:
在这里插入图片描述

if __name__ == "__main__":
    img = input("Please input name of image:")  #默认是string类型
    img = cv2.imread(img)
    
    img_gry = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    #plt.imshow显示cv2.imread读取的图像有色差发蓝的问题
    #重新整合r,g,b
    #img = Image.open(img)
    b, g, r = cv2.split(img)
    src_img = cv2.merge([r, g, b])
    
    img_demo = deepcopy(img_gry)
    snr = float(input("Please input signal noise ratio:"))
    img_salt = add_salt_noise(img_demo, snr)
    
    filiter_size = int(input("Please input size of filiter:"))
    median_blur = median_Blur_gray(img_salt, filiter_size)
    
    plt.figure("Image processing---MedianBlur")           #图像窗口名称
    plt.subplot(1, 3, 1)
    plt.imshow(img_gry, cmap='gray')
    plt.axis('off')         #关掉坐标轴
    plt.title("img_gry")
    
    
    plt.subplot(1, 3, 2)
    plt.imshow(img_salt, cmap='gray')
    plt.axis('off')         #关掉坐标轴
    plt.title("img_salt")
    
    plt.subplot(1, 3, 3)
    plt.imshow(median_blur, cmap='gray')
    plt.axis('off')         #关掉坐标轴
    plt.title("median_Blur")
    
    plt.tight_layout()  # 调整整体空白
    plt.subplots_adjust(left=None, bottom=None, right=None, top=None,
                wspace=None, hspace=None)  # 调整子图间距
    plt.savefig("reult.png", dpi=1000)
    plt.show()

运行过程:

Please input name of image: whitetulip.jpg
Please input signal noise ratio: 0.99
Please input size of filiter: 3

结果显示:
在这里插入图片描述

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值