爱生活,乐分享,大家好才是真的好!
返回顶部

CV总结之边缘检测

边缘检测

常见算子

边缘检测是图像处理和计算机视觉中的一个基本任务,目的是识别图像中物体的边界。边缘是图像中亮度变化显著的区域,通常标志着物体、表面或形状的边界。边缘检测对于后续的图像分析任务,如特征提取、目标识别和图像分割等,都是非常重要的。

常见边缘检测算法:

  1. Roberts算子:基于对角线方向的差分,使用两个2x2的卷积核来检测边缘。
  2. Prewitt算子:使用3x3的卷积核,对图像进行水平和垂直方向的差分,以检测边缘。
  3. Sobel算子:也是基于3x3的卷积核,但设计得更加精细,可以同时检测水平和垂直方向的边缘。
  4. Kirsch算子:使用8个不同方向的3x3卷积核来检测边缘,可以检测8个方向上的边缘。
  5. Robinson算子:类似于Kirsch算子,使用8个3x3的卷积核,但核的值有所不同。
  6. Canny算子:被认为是最优秀的边缘检测算子之一,它通过高斯滤波、梯度计算、非极大值抑制和双阈值检测等步骤来检测边缘。
  7. Laplacian算子:基于二阶导数,用于检测图像中的边缘,但对噪声较为敏感。
  8. Zero-Crossing算子:基于拉普拉斯算子,通过检测拉普拉斯算子的零交叉点来确定边缘位置。
  9. Shen-Castan滤波器:结合了Canny算子和Laplacian算子的特点,通过非线性映射和阈值处理来检测边缘。
  10. 结构化森林:一种较新的边缘检测方法,使用深度学习技术来检测边缘。

边缘检测算法的选择:

  • 简单性:对于需要快速响应的应用,可能会选择Roberts、Prewitt或Sobel算子。
  • 准确性:对于需要高精度边缘检测的应用,Canny算子通常是首选。
  • 抗噪声能力:Canny算子和结构化森林等算法具有较强的抗噪声能力。
  • 计算资源:对于计算资源有限的情况,可能会选择计算量较小的算法。

每种算法都有其特定的应用场景和优缺点,选择合适的算法需要根据具体的应用需求和条件来决定。

Canny算子

Canny算子是一种经典的边缘检测算法,由John F. Canny在1986年提出。它的目标是在保留图像原有属性的同时,显著减少图像的数据规模,找到最优的边缘检测解。Canny算子以其准确性高、低错误率、单一性和高效性而闻名,被广泛应用于各种计算机视觉系统中。以下是Canny算子的主要步骤和特点:

  1. 高斯滤波去噪:Canny算法的第一步是使用高斯滤波器平滑图像,以去除噪声。噪声和边缘都属于高频信号,高斯模糊可以减少噪声对边缘检测的影响。高斯核的大小会影响边缘检测的性能,核越大,对噪声的抑制越强,但边缘的定位误差也可能增加。
  2. 计算梯度强度和方向:Canny算法使用Sobel算子来计算图像的梯度幅度和方向。梯度的方向通常与边缘垂直,梯度的方向被归为四类:垂直、水平和两个对角线(即,0度、45度、90度和135度四个方向)。
  3. 非极大值抑制:在计算出梯度幅度和方向后,Canny算子通过非极大值抑制技术来过滤掉非边缘像素,使得边缘更加清晰。这个过程保留了每个像素点上梯度强度的极大值,过滤掉其他的值。
  4. 双阈值检测:经过非极大值抑制后,图像中仍然有很多噪声点。Canny算法使用双阈值技术,设定一个阈值上界和阈值下界,大于上界的认为是强边缘,小于下界的不是边缘,两者之间的是候选项(弱边缘),需进行进一步处理。
  5. 滞后技术跟踪边缘:最后,Canny算子使用滞后技术来跟踪边缘。如果某一像素位置和强边界相连的弱边界则认为是边缘,其他的弱边界则被删除。

Canny算子的优势在于其能够准确地找到图像中真实的边缘位置,并能够将边缘与噪声区分开,同时保持边缘的连续性和精确性。它适用于实时边缘检测,并且在MATLAB、OpenCV等常用图像处理工具中已有内置的Canny算子API。

使用OpenCV进行Canny边缘检测的Python代码如下:

首先,确保你已经安装了OpenCV库。如果没有安装,可以通过pip安装:

 
 
 
xxxxxxxxxx
 
 
 
 
pip install opencv-python
 

然后,你可以使用以下代码进行边缘检测:

 
 
 
xxxxxxxxxx
 
 
 
 
import cv2
import numpy as np
from matplotlib import pyplot as plt

# 读取图像(注意路径替换,并使用`cv2.IMREAD_GRAYSCALE`参数以灰度模式读取图像)
image = cv2.imread('path_to_your_image.jpg', cv2.IMREAD_GRAYSCALE)

# 检查图像是否成功加载
if image is None:
    print("Error: Image not found")
else:
    # 应用高斯模糊,减少图像噪声,有助于Canny算子更准确地检测边缘。
    blurred_image = cv2.GaussianBlur(image, (5, 5), 0)

    # 使用Canny算子检测边缘
    # 参数分别为:高阈值和低阈值(阈值决定了哪些边缘被认为是真实的边缘)
    edges = cv2.Canny(blurred_image, 50, 150)

    # 显示原图和边缘检测结果
    plt.figure(figsize=(10, 5))
    plt.subplot(121), plt.imshow(image, cmap='gray')
    plt.title('Original Image'), plt.xticks([]), plt.yticks([])
    plt.subplot(122), plt.imshow(edges, cmap='gray')
    plt.title('Edge Image'), plt.xticks([]), plt.yticks([])

    # 显示图像
    plt.show()
 

Kirsch算子

Kirsch算子是一种边缘检测算法,由R. Kirsch提出。它通过使用8个特定的3x3模板对图像进行卷积操作来检测边缘,这些模板代表了8个不同的方向,能够对图像上的8个特定边缘方向作出最大响应。在运算中,取这8个方向的最大值作为图像的边缘输出。

Kirsch算子的特点:

  1. 多方向响应:Kirsch算子的8个模板可以检测图像中的多个方向的边缘,这使得它在保持细节和抗噪声方面都有较好的效果。
  2. 边缘强度与方向:在计算边缘强度的同时可以得到边缘的方向,各方向间的夹角为45º。
  3. 最大响应值:对于图像上的每一个像素点,Kirsch算子通过卷积求导数,并取8个方向中的最大值作为该点的边缘输出。

Kirsch算子的模板:

Kirsch算子的8个模板如下所示,每个模板对应一个特定的方向,用于检测该方向上的边缘强度:

image-20241130111305623

这些模板通过与图像进行卷积操作来计算每个像素点的梯度幅度,然后选择最大梯度幅度的方向作为该点的边缘方向。Kirsch算子在图像处理领域,尤其是在边缘检测方面,因其有效性和鲁棒性而被广泛应用。

根据搜索结果,以下是使用Python和OpenCV实现Kirsch算子进行边缘检测的代码示例:

 
 
 
xxxxxxxxxx
 
 
import cv2
import numpy as np
from matplotlib import pyplot as plt

# 读取图像
image = cv2.imread('path_to_your_image.jpg', cv2.IMREAD_GRAYSCALE)

# 检查图像是否成功加载
if image is None:
    print("Error: Image not found")
else:
    # 自定义Kirsch算子的8个卷积核
    m1 = np.array([[5, 5, 5], [-3, 0, -3], [-3, -3, -3]])
    m2 = np.array([[-3, 5, 5], [-3, 0, 5], [-3, -3, -3]])
    m3 = np.array([[-3, -3, 5], [-3, 0, 5], [-3, -3, 5]])
    m4 = np.array([[-3, -3, -3], [-3, 0, 5], [-3, 5, 5]])
    m5 = np.array([[-3, -3, -3], [-3, 0, -3], [5, 5, 5]])
    m6 = np.array([[-3, -3, -3], [5, 0, -3], [5, 5, -3]])
    m7 = np.array([[5, -3, -3], [5, 0, -3], [5, -3, -3]])
    m8 = np.array([[5, 5, -3], [5, 0, -3], [-3, -3, -3]])
    filterlist = [m1, m2, m3, m4, m5, m6, m7, m8]  # 将各个方向的卷积核放到一起便于统一操作

    # 建立三维数组,第0维表示各个方向卷积后的值
    filtered_list = np.zeros((8, image.shape[0], image.shape[1]))

    # 对图像进行卷积操作
    for k in range(8):
        out = cv2.filter2D(image, cv2.CV_16S, filterlist[k])
        filtered_list[k] = out

    # 取八个方向中的最大值作为图像该点滤波之后的新的像素值
    final = np.max(filtered_list, axis=0)

    # 将像素值大于255的点等于255,小于255的点等于0
    final[np.where(final >= 255)] = 255
    final[np.where(final < 255)] = 0

    # 显示原图和边缘检测结果
    plt.figure(figsize=(10, 5))
    plt.subplot(121), plt.imshow(image, cmap='gray')
    plt.title('Original Image'), plt.xticks([]), plt.yticks([])
    plt.subplot(122), plt.imshow(final, cmap='gray')
 
 
    plt.title('Edge Image'), plt.xticks([]), plt.yticks([])

    # 显示图像
    plt.show()
 

Kirsch算子和Canny算子区别

Kirsch算子和Canny算子都是图像处理中用于边缘检测的算法,但它们在实现和特点上存在一些区别:

  1. 原理和方法

    • Kirsch算子:基于一阶导数的方法,使用8个方向的卷积核来检测边缘,每个卷积核对应一个方向,能够检测8个方向的边缘强度。
    • Canny算子:非微分边缘检测算子,它是一个多阶段的优化算子,包括高斯滤波、梯度计算、非极大值抑制和双阈值检测等步骤。
  2. 对噪声的敏感性

    • Kirsch算子:由于考虑了多个方向的像素突变,对噪声的抑制能力不如Canny算子,锐化效果可能不是很理想。
    • Canny算子:首先使用高斯滤波器平滑图像以去除噪声,因此对噪声不敏感,不容易受到噪声干扰。
  3. 边缘定位

    • Kirsch算子:边缘定位不如Canny算子精确,因为它是基于一阶导数的,而Canny算子结合了梯度的方向和幅度。
    • Canny算子:边缘定位较准确,常用于噪声较多,灰度渐变的图像。
  4. 计算复杂度

    • Kirsch算子:由于使用了8个卷积核,计算复杂度相对较高。
    • Canny算子:虽然实现较为复杂,但通常被认为是最有效的边缘检测方法之一,尤其是在实际项目如车道线检测中。
  5. 应用场景

    • Kirsch算子:适用于简单场景下的边缘检测,尤其是当需要快速响应时。
    • Canny算子:被广泛用于诸如车道线检测等实际项目中,是最有效的边缘检测方法之一。

总的来说,Canny算子在边缘检测的准确性、鲁棒性以及对噪声的抑制方面表现更好,而Kirsch算子则在计算速度上可能有一定优势,尤其是在对实时性要求较高的应用中。

结构化森林

结构化森林(Structured Forests)是一种基于深度学习的边缘检测方法,它在图像处理领域中被用来快速且有效地识别图像中的边缘。以下是结构化森林的一些关键特点和应用场景:

  1. 快速边缘检测:结构化森林能够快速预测局部掩模的边缘,这对于实时或近实时的边缘检测应用非常有用。
  2. 深度学习的应用:结构化森林结合了深度学习技术,通过训练一个结构化的随机森林模型来识别图像中的边缘。这种方法可以处理复杂的图像特征,并在多种场景下表现出良好的性能。
  3. 提高检测准确性:结构化森林在实验中显示出,它不仅提高了检测的准确性,而且减少了计算时间。这对于需要高效边缘检测的应用场景非常重要。
  4. 复杂背景下的应用:在复杂相似背景下,结构化森林能够有效地区分相似和随机的裂缝特征,这对于结构健康监测等领域尤为重要。
  5. 与其他算法的结合:结构化森林可以与其他图像处理技术结合使用,例如与Hough变换结合用于海天线检测。这种方法可以较好地忽略局部干扰边缘,强化边界提取,对复杂海天背景下的海天线检测具备鲁棒性和高准确性。
  6. OpenCV中的实现:在OpenCV库中,结构化森林被实现为一个快速的边缘检测工具。它可以通过提供预训练的模型文件来使用,这个模型文件可以在GitHub的opencv_extra仓库中找到。
  7. 代码实现:在实际应用中,结构化森林的边缘检测可以通过几行代码实现。首先,需要将输入图像转换为浮点类型,并除以255进行归一化。然后,使用createStructuredEdgeDetection函数创建一个边缘检测对象,并调用detectEdges方法来检测边缘。最后,可以通过非极大值抑制(NMS)进一步处理边缘图,以得到更清晰的边缘。

结构化森林因其快速、准确和在复杂背景下的有效性,成为了边缘检测领域中一个有前景的方法。

在OpenCV中,结构化森林(Structured Forests)边缘检测可以通过以下步骤进行调用和实现。这里提供一个简单的Python代码示例,展示如何使用OpenCV中的结构化森林进行边缘检测:

 
 
 
x
 
 
 
 
import cv2
import numpy as np

# 读取图像 (注意路径替换,并使用`cv2.IMREAD_GRAYSCALE`参数以灰度模式读取图像)
image = cv2.imread('path_to_your_image.jpg', cv2.IMREAD_GRAYSCALE)

# 检查图像是否成功加载
if image is None:
    print("Error: Image not found")
else:
    # 创建结构化森林边缘检测器
    structured_forest = cv2.createStructuredEdgeDetection()

    # 检测边缘
    edges = structured_forest.detectEdges(image)

    # 应用非极大值抑制(NMS)来细化边缘
    # flags=cv2.Canny_NORM_L2_GRADIENT来应用非极大值抑制,这有助于细化边缘。
    edges_nms = structured_forest.detectEdges(image,                                                           flags=cv2.Canny_NORM_L2_GRADIENT)

    # 显示原始图像和边缘检测结果
    cv2.imshow('Original Image', image)
    cv2.imshow('Edges', edges)
    cv2.imshow('Edges NMS', edges_nms)

    # 等待按键后关闭窗口
    cv2.waitKey(0)
    cv2.destroyAllWindows()
 
posted @ 2024-11-30 11:46  博观约取&厚积薄发  阅读(11)  评论(0编辑  收藏  举报
回到顶部
返回顶部