实验三 图像空间域平滑与锐化(Python实现)

一、实验目的与要求

  1. 加深对图像增强及边缘检测技术的感性认识,应用MATLAB工具箱自带的处理函数或自己编程完成相关的工作,分析处理结果,巩固所学理论知识。
  2. 熟练掌握空域滤波中常用的平滑和锐化滤波器,针对不同类型和强度的噪声,进行滤波处理,体会并正确评价滤波效果,了解不同滤波方式的使用场合,能够从理论上作出合理的解释。

二、实验内容

  1. 图像平滑(去噪):编写超限像素平滑法,灰度最相近的K个邻点平均法(函数名称可以自定义),并对上面实验1选择的噪声图片进行处理,显示处理前后的各个图像,分析不同方法对不同噪声的处理效果及其优缺点。
  2. 图像锐化:编写梯度锐化算法函数my_grad(method,T);参数method可以是梯度算子、Roberts算子、Prewitt和Sobel算子,T是梯度阈值,根据参数method和T选用不同的算子和阈值进行锐化处理,用二值图像表示处理结果,小于T的用黑色表示,大于等于T的用白色表示。显示处理前后的各个图像,分析不同方法对锐化效果及其优缺点。
     

三、实验​​​​​图像

四、实验​​​​​源程序


首先导入以下库:
import random
import numpy as np
import matplotlib.pyplot as plt
import cv2 as cv
import heapq


  1. 图像平滑(去噪):编写超限像素平滑法,灰度最相近的K个邻点平均法(函数名称可以自定义),并对上面实验1选择的噪声图片进行处理,显示处理前后的各个图像,分析不同方法对不同噪声的处理效果及其优缺点。

    A. 超限像素平滑法
    def neighborhood_smooth(img, k=4):
        """
        局部平滑法
        k:默认为4邻域
        """
        h, w = img.shape[:2]
        smooth_img = np.zeros((h - 2, w - 2), dtype=np.uint8)
        for i in range(1, h - 1):
            for j in range(1, w - 1):
                smooth_img[i - 1, j - 1] = (int(img[i - 1, j]) + int(img[i + 1, j])
                                            + int(img[i, j - 1]) + int(img[i, j + 1])) / k
        return smooth_img
    
    
    def Overite_pixel_smoothing_method(img, T=50):
        """
        超限像素平滑法
        img:椒盐噪声/高斯噪声图片
        T:默认50
        """
        # 首先调用局部平滑法进行处理
        neighborhood_img = neighborhood_smooth(img, k=4)
        h, w = neighborhood_img.shape[:2]
        for i in range(h):
            for j in range(w):
                if np.abs(neighborhood_img[i, j] - img[i, j]) <= T:
                    neighborhood_img[i, j] = img[i, j]
        return neighborhood_img
    
    
    # 读入图像
    src = cv.imread("rice.png", 0)  # 以灰度图像读入
    img = src.copy()
    
    # 生成噪声图片
    img_sp = sp_noise(img, prob=0.02)  # 添加椒盐噪声,噪声比例为0.02
    img_gauss = gasuss_noise(img, mean=0, var=0.01)  # 添加高斯噪声,均值为0,方差为0.01
    
    # 超限像素平滑法处理两种噪声图片
    result_img_sp = Overite_pixel_smoothing_method(img_sp, T=60)
    result_img_gauss = Overite_pixel_smoothing_method(img_gauss, T=60)
    
    # 显示图像
    plt.figure(figsize=(10, 8), dpi=100)
    plt.subplot(131)
    plt.imshow(src, cmap=plt.cm.gray)
    plt.title("原图")
    plt.subplot(232)
    plt.imshow(img_sp, cmap=plt.cm.gray)
    plt.title("椒盐噪声图片")
    plt.subplot(233)
    plt.imshow(result_img_sp, cmap=plt.cm.gray)
    plt.title("超限像素平滑法处理椒盐噪声")
    plt.subplot(235)
    plt.imshow(img_gauss, cmap=plt.cm.gray)
    plt.title("高斯噪声图片")
    plt.subplot(236)
    plt.imshow(result_img_gauss, cmap=plt.cm.gray)
    plt.title("超限像素平滑法处理高斯噪声")
    plt.show()

    (注:本题中用到的添加噪声的函数 sp_noise 和 gasuss_noise 为:)
    def sp_noise(image, prob):
        """
        添加椒盐噪声
        prob:噪声比例
        """
        output = np.zeros(image.shape, np.uint8)
        thres = 1 - prob
        for i in range(image.shape[0]):
            for j in range(image.shape[1]):
                rdn = random.random()
                if rdn < prob:
                    output[i][j] = 0
                elif rdn > thres:
                    output[i][j] = 255
                else:
                    output[i][j] = image[i][j]
        return output
    
    
    def gasuss_noise(image, mean=0, var=0.001):
        """
            添加高斯噪声
            mean : 均值
            var : 方差
        """
        image = np.array(image / 255, dtype=float)
        noise = np.random.normal(mean, var ** 0.5, image.shape)
        out = image + noise
        if out.min() < 0:
            low_clip = -1.
        else:
            low_clip = 0.
        out = np.clip(out, low_clip, 1.0)
        out = np.uint8(out * 255)
        return out

    B. 灰度最相近的K个邻点平均法
    (仅写出了算法函数)

    def K_adjacent_point_average_method(img, s=3, k=5):
        """
        灰度最相近的k个邻点平均法
        :param img: 传入的噪声图片
        :param s: 默认为3*3的领域
        :param k: 默认为5,包括中心像素
        :return: 返回图片
        """
        h, w = img.shape[:2]
        smooth_img = np.zeros((h - 2, w - 2), dtype=np.uint8)
        dis = int((s - 1) / 2)
        temp = []
        min_index = []
        for i in range(1, h - 1):
            for j in range(1, w - 1):
                temp = img[i - dis:i + dis + 1, j - dis:j + dis + 1].ravel()  # 将3*3的切片转换为1维数组
                temp2 = [np.abs(k - int(img[i, j])) for k in temp]  # 将列表中每个元素减去中心元素并取绝对值
                min_num = heapq.nsmallest(k, temp2)  # 找出结果列表中最小的k个数
                sum = 0
                for t in min_num:
                    index = temp2.index(t)  # 根据min_num寻找原列表的索引
                    sum += temp[index]
                    temp2[index] = -1
                smooth_img[i - 1, j - 1] = np.round(sum / k)  # 给新图像赋值
        return smooth_img

  2. 图像锐化:编写梯度锐化算法函数my_grad(method,T);参数method可以是梯度算子、Roberts算子、Prewitt和Sobel算子,T是梯度阈值,根据参数method和T选用不同的算子和阈值进行锐化处理,用二值图像表示处理结果,小于T的用黑色表示,大于等于T的用白色表示。显示处理前后的各个图像,分析不同方法对锐化效果及其优缺点。

    class Arth():
        Grad = 0
        Roberts = 1
        Prewitt = 2
        Sobel = 3
    
    def my_grad(img, method, T=50):
        """
        梯度锐化算法
        :param img:输入的灰度图像
        :param method:不同的算子
        :param T:梯度阈值,默认=50
        """
        h, w = img.shape[:2]
        new_img = np.zeros((h, w), dtype=np.uint8)
        for i in range(h - 1):
            for j in range(w - 1):
                # 梯度算子
                if method == Arth.Grad:
                    grad = abs(int(img[i, j + 1]) - int(img[i, j])) + abs(int(img[i + 1, j]) - int(img[i, j]))
                    new_img[i, j] = 255 if grad >= T else 0
                # Roberts算子
                if method == Arth.Roberts:
                    grad = abs(int(img[i + 1, j + 1]) - int(img[i, j])) + abs(int(img[i + 1, j]) - int(img[i, j + 1]))
                    new_img[i, j] = 255 if grad >= T else 0
        for i in range(h - 2):
            for j in range(w - 2):
                # Prewitt算子
                if method == Arth.Prewitt:
                    f_y = sum(img[i:i + 3, j:j + 3][2]) - sum(img[i:i + 3, j:j + 3][0])
                    f_x = sum(img[i:i + 3, j:j + 3][:, 2]) - sum(img[i:i + 3, j:j + 3][:, 0])
                    grad = abs(f_y) + abs(f_x)
                    new_img[i, j] = 255 if grad >= T else 0
                # Sobel算子
                if method == Arth.Sobel:
                    f_y = sum(img[i:i + 3, j:j + 3][2]) - sum(img[i:i + 3, j:j + 3][0]) \
                          + img[i + 2, j + 1] - img[i, j + 1]
                    f_x = sum(img[i:i + 3, j:j + 3][:, 2]) - sum(img[i:i + 3, j:j + 3][:, 0]) \
                          + img[i + 1, j + 2] - img[i + 1, j]
                    grad = abs(f_y) + abs(f_x)
                    new_img[i, j] = 255 if grad >= T else 0
        return new_img
    
    
    # 读入图像
    src = cv.imread("rice.png", 0)  # 以灰度图像读入
    img = src.copy()
    
    Grad_img = my_grad(img, Arth.Grad, 50)
    Roberts_img = my_grad(img, Arth.Roberts, 50)
    Prewitt_img = my_grad(img, Arth.Prewitt, 70)
    Sobel_img = my_grad(img, Arth.Sobel, 70)
    
    # 显示图像
    plt.figure(figsize=(10, 8), dpi=200)
    plt.subplot(131)
    plt.imshow(src, cmap=plt.cm.gray)
    plt.title("原图")
    plt.subplot(232)
    plt.imshow(Grad_img, cmap=plt.cm.gray)
    plt.title("梯度算子")
    plt.subplot(233)
    plt.imshow(Roberts_img, cmap=plt.cm.gray)
    plt.title("Roberts算子")
    plt.subplot(235)
    plt.imshow(Prewitt_img, cmap=plt.cm.gray)
    plt.title("Prewitt算子")
    plt.subplot(236)
    plt.imshow(Sobel_img, cmap=plt.cm.gray)
    plt.title("Sobel算子")
    plt.show()

    另一组图像(T=20,20,60,60):

    扫描二维码关注公众号,回复: 14222360 查看本文章

猜你喜欢

转载自blog.csdn.net/qq_45832961/article/details/124111715