• OpenCV 的几种查找图像中轮廓边缘的方法


     原始图片:

     

    1、Sobel()

    Sobel 算子结合了高斯平滑和微分,用于计算图像的梯度,从而突出显示边缘。

    1. import cv2
    2. # 读取图像
    3. image = cv2.imread('image.png', cv2.IMREAD_GRAYSCALE)
    4. # 使用 Sobel 算子查找水平和垂直边缘
    5. sobel_x = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=3)
    6. sobel_y = cv2.Sobel(image, cv2.CV_64F, 0, 1, ksize=3)
    7. # 叠加水平和垂直边缘
    8. edges = cv2.addWeighted(cv2.convertScaleAbs(sobel_x), 0.5, cv2.convertScaleAbs(sobel_y), 0.5, 0)
    9. # 显示结果
    10. cv2.imshow("Original Image", image)
    11. cv2.imshow("Edges", edges)
    12. cv2.waitKey(0)
    13. cv2.destroyAllWindows()

    函数原型:

    sobel = cv2.Sobel(src, ddepth, dx, dy, ksize, scale, delta, borderType) 

    参数说明:

    1. src: 输入图像(单通道,例如灰度图)。
    2. ddepth: 输出图像的深度(例如 cv2.CV_64F 表示 64 位浮点数)。
    3. dx: x 方向上的导数阶数(0表示没有导数,1表示一阶导数)。
    4. dy: y 方向上的导数阶数(与 dx 类似)。
    5. ksize: Sobel 核的大小,必须是 1, 3, 5 或 7 等奇数。
    6. scale: 可选值,缩放导数结果,以便调整图像亮度(默认值为 1)。
    7. delta: 可选值,在存储之前添加到结果中的值(默认值为 0)。
    8. borderType: 边界类型,用于确定图像边界(默认值为 cv2.BORDER_DEFAULT)。

     2、Scharr()

    Scharr 算子是一种改进的 Sobel 算子,适用于增强边缘检测的精度,在正常的 Sobel 核的尺寸上有更好的性能。

    scharr_x = cv2.Scharr(src, ddepth, dx, dy, scale, delta, borderType)
    

    参数说明:

    • 与 cv2.Sobel() 相同,只是 ksize 参数被硬编码为 3。

    1. import cv2
    2. import numpy as np
    3. # 读取图像并转换为灰度图
    4. image = cv2.imread('image.png', cv2.IMREAD_GRAYSCALE)
    5. # 使用 Scharr 算子计算 x 和 y 方向上的梯度
    6. grad_x = cv2.Scharr(image, cv2.CV_64F, 1, 0)
    7. grad_y = cv2.Scharr(image, cv2.CV_64F, 0, 1)
    8. # 将梯度取绝对值并转换为 8 位图像
    9. abs_grad_x = cv2.convertScaleAbs(grad_x)
    10. abs_grad_y = cv2.convertScaleAbs(grad_y)
    11. # 合并 x 方向和 y 方向的梯度
    12. scharr = cv2.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0)
    13. # 显示图像
    14. cv2.imshow('Scharr Edge Detection', scharr)
    15. cv2.waitKey(0)
    16. cv2.destroyAllWindows()

     

    3、Canny()

    Canny 边缘检测是一种多级边缘检测算法,效果较为显著,常用来检测图像中的明显边缘。

     函数原型:

    edges = cv2.Canny(image, threshold1, threshold2, apertureSize, L2gradient)

    参数说明:

    • image: 输入图像,通常是灰度图。
    • threshold1: 较低的阈值,用于边缘检测的滞后阈值过程。
    • threshold2: 较高的阈值。
    • apertureSize: Sobel 算子的大小,默认值为 3。
    • L2gradient: 可选参数,用于计算图像梯度幅值的标志。如果为 True,则使用更精确的 L2 范数计算梯度,否则使用 L1 范数。
      1. import cv2
      2. # 读取图像并转换为灰度图
      3. image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)
      4. # 使用 Canny 边缘检测
      5. edges = cv2.Canny(image, 100, 200)
      6. # 显示图像
      7. cv2.imshow('Canny Edge Detection', edges)
      8. cv2.waitKey(0)
      9. cv2.destroyAllWindows()

    4、Laplacian ()

    Laplacian 算子是一种二阶导数算子,用于检测图像中的边缘。

    laplacian = cv2.Laplacian(src, ddepth, ksize, scale, delta, borderType)
    

    参数说明:

    • src: 输入图像。
    • ddepth: 输出图像的深度。
    • ksize: Laplacian 算子的大小,必须是正奇数。
    • scale: 可选参数,用于缩放导数值,默认值为 1。
    • delta: 可选参数,在存储之前添加到结果中的值,默认值为 0。
    • borderType: 边界模式,默认值为 cv2.BORDER_DEFAULT
      1. import cv2
      2. import numpy as np
      3. # 读取图像并转换为灰度图
      4. image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)
      5. # 使用 Laplacian 边缘检测
      6. laplacian = cv2.Laplacian(image, cv2.CV_64F)
      7. # 将结果转换为 8 位图像
      8. laplacian = cv2.convertScaleAbs(laplacian)
      9. # 显示图像
      10. cv2.imshow('Laplacian Edge Detection', laplacian)
      11. cv2.waitKey(0)
      12. cv2.destroyAllWindows()

    5、Prewitt算子

    Prewitt 算子是另一种一阶导数算子,可以检测水平和垂直边缘。虽然 OpenCV 没有直接提供 cv2.prewitt() 函数,但可以使用 cv2.filter2D 函数自定义 Prewitt 核来实现。 

    1. import cv2
    2. import numpy as np
    3. # 读取图像并转换为灰度图
    4. image = cv2.imread('image.png', cv2.IMREAD_GRAYSCALE)
    5. # 定义 Prewitt 核
    6. prewitt_kernel_x = np.array([[1, 0, -1],
    7. [1, 0, -1],
    8. [1, 0, -1]])
    9. prewitt_kernel_y = np.array([[1, 1, 1],
    10. [0, 0, 0],
    11. [-1, -1, -1]])
    12. # 使用 Prewitt 核进行边缘检测
    13. grad_x = cv2.filter2D(image, cv2.CV_64F, prewitt_kernel_x)
    14. grad_y = cv2.filter2D(image, cv2.CV_64F, prewitt_kernel_y)
    15. # 计算梯度幅值
    16. abs_grad_x = cv2.convertScaleAbs(grad_x)
    17. abs_grad_y = cv2.convertScaleAbs(grad_y)
    18. prewitt = cv2.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0)
    19. # 显示图像
    20. cv2.imshow('Prewitt Edge Detection', prewitt)
    21. cv2.waitKey(0)
    22. cv2.destroyAllWindows()

      

     6、Roberts Cross算子

    罗伯特交叉算子是一种简单且快速的边缘检测算子,适用于检测图像的对角边缘。OpenCV 中没有直接提供罗伯特交叉算子,但可以通过自定义卷积核实现。

    1. import cv2
    2. import numpy as np
    3. # 读取图像并转换为灰度图
    4. image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)
    5. # 定义 Roberts 核
    6. roberts_kernel_x = np.array([[1, 0],
    7. [0, -1]])
    8. roberts_kernel_y = np.array([[0, 1],
    9. [-1, 0]])
    10. # 使用 Roberts 核进行边缘检测
    11. grad_x = cv2.filter2D(image, cv2.CV_64F, roberts_kernel_x)
    12. grad_y = cv2.filter2D(image, cv2.CV_64F, roberts_kernel_y)
    13. # 计算梯度幅值
    14. abs_grad_x = cv2.convertScaleAbs(grad_x)
    15. abs_grad_y = cv2.convertScaleAbs(grad_y)
    16. roberts = cv2.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0)
    17. # 显示图像
    18. cv2.imshow('Roberts Edge Detection', roberts)
    19. cv2.waitKey(0)
    20. cv2.destroyAllWindows()

    7、自定义卷积核

    还可以通过自定义卷积核来进行边缘检测。

    1. import cv2
    2. import numpy as np
    3. # 读取图像并转换为灰度图
    4. image = cv2.imread('image.png', cv2.IMREAD_GRAYSCALE)
    5. # 定义自定义卷积核
    6. custom_kernel = np.array([[-1, -1, -1],
    7. [-1, 7, -1],
    8. [-1, -1, -1]])
    9. # 使用自定义卷积核进行边缘检测
    10. custom_edges = cv2.filter2D(image, cv2.CV_64F, custom_kernel)
    11. # 将结果转换为 8 位图像
    12. custom_edges = cv2.convertScaleAbs(custom_edges)
    13. # 显示图像
    14. cv2.imshow('Custom Kernel Edge Detection', custom_edges)
    15. cv2.waitKey(0)
    16. cv2.destroyAllWindows()

     8、基于直方图的边缘检测

    基于直方图的方法,通过分析图像的灰度直方图来检测边缘。

    1. import cv2
    2. import numpy as np
    3. # 读取图像并转换为灰度图
    4. image = cv2.imread('image.png', cv2.IMREAD_GRAYSCALE)
    5. # 计算图像的直方图
    6. hist = cv2.calcHist([image], [0], None, [256], [0, 256])
    7. # 找到直方图的峰值
    8. min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(hist)
    9. # 使用峰值作为阈值进行二值化处理
    10. _, binary = cv2.threshold(image, max_loc[1] - 30, 255, cv2.THRESH_BINARY)
    11. # 显示图像
    12. cv2.imshow('Histogram Based Edge Detection', binary)
    13. cv2.waitKey(0)
    14. cv2.destroyAllWindows()

     

    9、adaptiveThreshold()

    自适应阈值

    自适应阈值可以在照明不均匀的情况下检测边缘。

    函数原型:

    cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst])
    

    参数说明:

    • src:输入图像,应为灰度图像(单通道)。
    • maxValue:指定在满足条件时给输出像素赋予的最大值(通常为255)。
    • adaptiveMethod:自适应方法。可选值有:
      • cv2.ADAPTIVE_THRESH_MEAN_C:基于邻域均值的自适应阈值化方法。
      • cv2.ADAPTIVE_THRESH_GAUSSIAN_C:基于邻域加权均值的自适应阈值化方法。
    • thresholdType:阈值类型,应为 cv2.THRESH_BINARY 或 cv2.THRESH_BINARY_INV
    • blockSize:指定用于计算阈值的邻域大小,一般为奇数。
    • C:从计算的平均值或加权平均值中减去的常数。

    1. import cv2
    2. # 读取图像并转换为灰度图
    3. image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)
    4. # 自适应阈值
    5. adaptive_threshold = cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
    6. # 显示图像
    7. cv2.imshow('Adaptive Threshold Edge Detection', adaptive_threshold)
    8. cv2.waitKey(0)
    9. cv2.destroyAllWindows()

     

    10、threshold()

    阈值化 (cv2.threshold)

    简单的全局阈值化方法,通过固定的阈值来二值化图像以检测边缘。

    1. import cv2
    2. # 读取图像并转换为灰度图
    3. image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)
    4. # 全局阈值化
    5. _, threshold = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY)
    6. # 显示图像
    7. cv2.imshow('Global Threshold Edge Detection', threshold)
    8. cv2.waitKey(0)
    9. cv2.destroyAllWindows()

     

  • 相关阅读:
    uniapp引入Tensorflow.js所会发生的一些问题( 主要发布平台 微信小程序 )
    K8S知识点(九)
    debian/ubuntu/windows配置wiregurad内网服务器(包含掉线自启动)
    selenium中webdriver常用的ChromeOptions参数
    C#,骑士游历问题(Knight‘s Tour Problem)的恩斯多夫(Warnsdorff‘s Algorithm)算法与源代码
    图解LeetCode——1235. 规划兼职工作(难度:困难)
    PostgeSQL修改数据库名称
    micro-ros arduino esp32 ros2 笔记
    使用MySQL Workbench进行数据库创建
    【LeetCode】24. 两两交换链表中的节点
  • 原文地址:https://blog.csdn.net/xulibo5828/article/details/139394245