0
点赞
收藏
分享

微信扫一扫

【youcans 的 OpenCV 例程200篇】151. 边缘检测中的平滑处理


【youcans 的 OpenCV 例程200篇】151. 边缘检测中的平滑处理


2. 点、线和边缘检测

2.4 边缘检测的常用梯度算子

边缘检测的基本方法通常是基于一阶导数和二阶导数的,因此需要进行图像的梯度计算。图像的梯度可以用一阶导数和二阶偏导数来求解。
根据梯度算子的定义和基本公式,可以发展多种不同的计算算法,称为梯度算子。对于图像的梯度计算,通常采用模板(卷积核)对原图像进行卷积运算来实现。

Robert 梯度算子:
简单的交叉差分算法,利用局部差分算子寻找边缘,采用对角线相邻两像素差作为梯度值检测边缘。形式简单,计算速度快,但对噪声敏感,无法抑制噪声。

Prewitt 算子:
利用两个方向模板与图像进行邻域卷积,一个方向模板检测水平边缘,另一个检测垂直边缘。能够抑制噪声,但对边缘的定位较 Roberts 算子差。

Sobel 算子:
是高斯平滑和微分求导的联合运算,抗噪声能力强。考虑了距离对权值的影响,距离越远的像素的影响越小。可以通过快速卷积实现,简单有效,应用广泛。

Isotropic Sobel 算子:
权值反比于中心距,具有各向同性,沿不同方向检测边缘时梯度幅度一致。

Scharr 算子:
是 Sobel 算子在 ksize=3 时的优化,在平滑部分中心元素占的权重更大,相当于使用更瘦高的平滑模板。与 Sobel 的速度相同,精度更高。

Lapacian 算子:
二阶微分算子,具有各向同向性,与坐标轴无关(无法检测方向)。对噪声非常敏感,可以先进行阈值处理或平滑处理。

这些基本的一阶、二阶微分算子如 Robert、Sobel、Prewitt、Laplacian 等,本质上都可以用于检测边缘,也被称为边缘检测算子。进一步地,考虑边缘和噪声的性质,可以改进边缘检测算子,如 Marr-Hildreth 算子、Canny 算子。


例程 11.5 边缘检测算子:平滑处理的影响

本例程比较平滑操作对边缘检测的影响。

原始图像分辨率高,精细的细节丰富,使图像中主要边缘检测过于复杂。因此,先对原图像进行平滑处理,再进行梯度卷积运算,可以获得图像的主要边缘,忽略不必要的细节。

    # 11.5 边缘检测算子:平滑操作的影响
    img = cv2.imread("../images/Fig1016a.tif", flags=0)  # 读取为灰度图像

    # 自定义卷积核
    # Roberts 边缘算子
    kernel_Roberts_x = np.array([[1, 0], [0, -1]])
    kernel_Roberts_y = np.array([[0, -1], [1, 0]])
    # Prewitt 边缘算子
    kernel_Prewitt_x = np.array([[-1, 0, 1], [-1, 0, 1], [-1, 0, 1]])
    kernel_Prewitt_y = np.array([[1, 1, 1], [0, 0, 0], [-1, -1, -1]])
    # Sobel 边缘算子
    kernel_Sobel_x = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]])
    kernel_Sobel_y = np.array([[1, 2, 1], [0, 0, 0], [-1, -2, -1]])

    # 梯度算子直接卷积运算
    imgRoberts_x = cv2.filter2D(img, -1, kernel_Roberts_x)
    imgRoberts_y = cv2.filter2D(img, -1, kernel_Roberts_y)
    imgRoberts = np.uint8(cv2.normalize(abs(imgRoberts_x) + abs(imgRoberts_y), None, 0, 255, cv2.NORM_MINMAX))
    imgPrewitt_x = cv2.filter2D(img, -1, kernel_Prewitt_x)
    imgPrewitt_y = cv2.filter2D(img, -1, kernel_Prewitt_y)
    imgPrewitt = np.uint8(cv2.normalize(abs(imgPrewitt_x) + abs(imgPrewitt_y), None, 0, 255, cv2.NORM_MINMAX))
    imgSobel_x = cv2.filter2D(img, -1, kernel_Sobel_x)
    imgSobel_y = cv2.filter2D(img, -1, kernel_Sobel_y)
    imgSobel = np.uint8(cv2.normalize(abs(imgSobel_x) + abs(imgSobel_y), None, 0, 255, cv2.NORM_MINMAX))
    # 先图像平滑,再用梯度算子
    imgBlur = cv2.blur(img, (5,5))  # Blur 平滑后再做 Laplacian 变换
    imgRoberts_x = cv2.filter2D(imgBlur, -1, kernel_Roberts_x)
    imgRoberts_y = cv2.filter2D(imgBlur, -1, kernel_Roberts_y)
    blurRoberts = np.uint8(cv2.normalize(abs(imgRoberts_x) + abs(imgRoberts_y), None, 0, 255, cv2.NORM_MINMAX))
    imgPrewitt_x = cv2.filter2D(imgBlur, -1, kernel_Prewitt_x)
    imgPrewitt_y = cv2.filter2D(imgBlur, -1, kernel_Prewitt_y)
    blurPrewitt = np.uint8(cv2.normalize(abs(imgPrewitt_x) + abs(imgPrewitt_y), None, 0, 255, cv2.NORM_MINMAX))
    imgSobel_x = cv2.filter2D(imgBlur, -1, kernel_Sobel_x)
    imgSobel_y = cv2.filter2D(imgBlur, -1, kernel_Sobel_y)
    blurSobel = np.uint8(cv2.normalize(abs(imgSobel_x) + abs(imgSobel_y), None, 0, 255, cv2.NORM_MINMAX))

    plt.figure(figsize=(9, 6))
    plt.subplot(231), plt.title('Roberts'), plt.imshow(imgRoberts, cmap='gray'), plt.axis('off')
    plt.subplot(234), plt.title('Blur-Roberts'), plt.imshow(blurRoberts, cmap='gray'), plt.axis('off')
    plt.subplot(232), plt.title('Prewitt'), plt.imshow(imgPrewitt, cmap='gray'), plt.axis('off')
    plt.subplot(235), plt.title('Blur-Prewitt'), plt.imshow(blurPrewitt, cmap='gray'), plt.axis('off')
    plt.subplot(233), plt.title('Sobel'), plt.imshow(imgSobel, cmap='gray'), plt.axis('off')
    plt.subplot(236), plt.title('Blur-Sobel'), plt.imshow(blurSobel, cmap='gray'), plt.axis('off')
    plt.tight_layout()
    plt.show()

在这里插入图片描述


(本节完)


版权声明:

youcans@xupt 原创作品,转载必须标注原文链接:(https://blog.csdn.net/youcans/article/details/124091831)

Copyright 2022 youcans, XUPT
Crated:2022-4-10


举报

相关推荐

0 条评论