文章目录
- 前言
- 一、什么是边缘检测?
- 二、算法分类
- 1、Sobel算子
- 2、Scharr算子
- 3、Canny边缘检测
- 3.1 Canny检测的优点
- 3.2 Canny 边缘检测分为 4 个部分
- 3.2.1 、图像降噪
- 3.2.2 、梯度计算
- 3.2.3 、非极大值抑制
- 3.2.4 、双阈值边界跟踪
- 4、算法比较
- 三、代码实现
- 总结
前言
在计算机视觉的世界中,边缘检测如同人类视觉系统对物体轮廓的敏锐感知。它让机器能够从纷繁复杂的图像中提取关键的结构信息,成为目标识别、自动驾驶、医学影像分析等领域的基石。本文将深入浅出地解析边缘检测的核心原理、经典算法及其实际应用。
一、什么是边缘检测?
边缘检测是图像处理中用于识别图像亮度急剧变化区域的技术。这些变化通常对应物体边界、纹理突变或光照差异,例如一张桌子与背景的分界线,或人脸与头发的轮廓。通过检测这些边缘,计算机能够将图像简化为线条组成的“骨架”,为后续分析(如物体识别)提供高效的数据基础。
边缘检测经典算法对比更新(增加Scharr算子)
二、算法分类
1、Sobel算子
Sobel 算子是一种离散的微分算子,该算子结合了高斯平滑和微分求导运算。该算子利用局部差分寻找边缘,计算所得的是一个梯度的近似值。
2、Scharr算子
Scharr 算子是 Soble 算子在 ksize=3 时的优化,与 Soble 的速度相同,且精度更高。 Scharr 算子与 Sobel 算子的不同点是在平滑部分,其中心元素占的权重更重,相当于使用较小标准差的高斯函数,也就是更瘦高的模板。
3、Canny边缘检测
3.1 Canny检测的优点
√ 低错误率。因为一般的边缘检测算子可能存在检测到伪边缘的情况,因此 Canny 算法检测到的边缘尽可能地是真实的边缘。
√ 较好地定位边缘点。由检测器标记的边缘点与真实边缘点中心尽可能地接近。
√ 单一的边缘响应。图像中的边缘只标记出一次。
3.2 Canny 边缘检测分为 4 个部分
3.2.1 、图像降噪
图像去噪是进行边缘检测的第一步,通过去噪可以去除图像中的一些噪点,从而使边缘检测时免受噪点干扰。高斯滤波。
3.2.2 、梯度计算
要进行边缘检测,就需要得到图像梯度信息,根据图像的梯度幅值和梯度方向来确定边缘,一般均采用 sobel 算子对图像进行梯度幅值与梯度方向计算。
3.2.3 、非极大值抑制
3.2.4 、双阈值边界跟踪
4、算法比较
三、代码实现
# #读取图像观看效果 sobel算子
zl = cv2.imread('zl.png',cv2.IMREAD_GRAYSCALE)#不用灰度试试效果
zl_x_64 = cv2.Sobel(zl,cv2.CV_64F,dx=1,dy=0)#默认int8改为float64,可保存负数
zl_x_full = cv2.convertScaleAbs(zl_x_64)#转换为绝对值,负数转换为正数
zl_y_64 = cv2.Sobel(zl,cv2.CV_64F,dx=0,dy=1)#默认int8改为float64,可保存负数
zl_y_full = cv2.convertScaleAbs(zl_y_64)#转换为绝对值,负数转换为正数
zl_xy_sobel_full = cv2.addWeighted(zl_x_full,1,zl_y_full,1,0)
cv2.imshow('zl_xy_sobel_full',zl_xy_sobel_full)
cv2.waitKey(0)
# #
# # #Scharr 算子
# # # cv.Scharr(src, ddepth, dx, dy[, dst[, scale[, delta[, borderType]]]])
# # # src:输入图像
# # # ddepth:输出图片的数据深度,由输入图像的深度进行选择
# # # dx:x 轴方向导数的阶数
# # # dy:y 轴方向导数的阶数
zl = cv2.imread('zl.png',cv2.IMREAD_GRAYSCALE)
zl_x_64 = cv2.Scharr(zl,cv2.CV_64F,dx=1,dy=0)#默认int8改为float64,可保存负数
zl_x_full = cv2.convertScaleAbs(zl_x_64)#转换为绝对值,负数转换为正数
zl_y_64 = cv2.Scharr(zl,cv2.CV_64F,dx=0,dy=1)#默认int8改为float64,可保存负数
zl_y_full = cv2.convertScaleAbs(zl_y_64)#转换为绝对值,负数转换为正数
zl_xy_Scharr_full = cv2.addWeighted(zl_x_full,1,zl_y_full,1,0)
cv2.imshow('zl_xy_Scharr_full',zl_xy_Scharr_full)
cv2.waitKey(0)
#$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
# #cv2.Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]])
# # 参数说明:
# # src:输入图像,可以是灰度图像,也可以是多通道的彩色图像
# # ddepth:输出图片的数据深度:
# # ksize:计算二阶导数滤波器的孔径大小,必须为正奇数,可选项
# # scale:缩放比例因子,可选项,默认值为 1
# # delta:输出图像的偏移量,可选项,默认值为 0zl = cv2.imread('zl.png',cv2.IMREAD_GRAYSCALE)
zl_lap = cv2.Laplacian(zl,cv2.CV_64F)
zl_lap_full = cv2.convertScaleAbs(zl_lap)#转换为绝对值,负数转换为正数
cv2.imshow('zl_lap_full',zl_lap_full)
cv2.waitKey(0)
#
# # canny边缘检测
# # cv.Canny( image, threshold1, threshold2[, apertureSize[, L2gradient]])
# # image 为输入图像。
# # threshold1 表示处理过程中的第一个阈值。fL
# # threshold2 表示处理过程中的第二个阈值。fH
#
zl = cv2.imread('kobe.jpg',cv2.IMREAD_GRAYSCALE)
cv2.imshow('zl',zl)
cv2.waitKey(0)
zl_canny = cv2.Canny(zl,100,150)#低,高
cv2.imshow('zl_canny',zl_canny)
cv2.waitKey(0)
总结
从Sobel到Canny,再到基于深度学习的HED(Holistically-Nested Edge Detection),边缘检测技术不断演进,但其核心目标始终如一:让机器“看见”世界的轮廓。随着AI与边缘计算的融合,未来的边缘检测将更智能、更高效,成为机器视觉的“火眼金睛”。