opencv(边缘检测)
本文介绍了OpenCV中四种边缘检测方法:1)Sobel算子通过计算x/y方向梯度检测边缘,需注意负梯度处理;2)Scharr算子作为Sobel的优化版,采用3x3核实现更高精度;3)Laplacian算子基于二阶梯度直接检测各方向边缘;4)Canny边缘检测通过高斯去噪、梯度计算、非极大值抑制和双阈值筛选四个步骤获得更清晰的边缘。文章详细说明了各方法的函数参数、实现原理和代码示例,并展示了不同方
一、边缘检测
1.sobel算子
cv2.Sobel() 是 OpenCV 实现索贝尔算子(Sobel Operator) 的函数,它通过计算图像的梯度来检测边缘。
cv2.Sobel(src, ddepth, dx, dy, ksize=None)
src : 输入图像(通常是灰度图)
ddepth: 输出图像的深度(推荐用 cv2.CV_64F,避免梯度为负时被截断)
dx : x 方向的导数阶数(0/1/2,边缘检测常用 1)
dy : y 方向的导数阶数(0/1/2,边缘检测常用 1)
ksize : 核的大小(奇数,如 3/5/7,默认 3;设为 -1 时用 Scharr 算子,效果更好)
代码:用x方向的导数阶数
yuan = cv2.imread('2_GRAY.jpg')
cv2.imshow('yuan',yuan)
cv2.waitKey(0)
##x方向上的边缘
yuan_x=cv2.Sobel(yuan,-1,dx=1,dy=0)
cv2.imshow('yuan_x',yuan_x)
cv2.waitKey(0)
#x方向上的边缘,包括负数信息(右端),但显示不出来,因为范围是(0~255)
yuan_x_64=cv2.Sobel(yuan,cv2.CV_64F,dx=1,dy=0)#默认uint8改为float64,可保存负数
cv2.imshow('yuan_x_64',yuan_x_64)
cv2.waitKey(0)
##x方向上的边缘,包括负数信息,进行取绝对值的操作,右端的负值信息就可以显示出来了
yuan_x_full=cv2.convertScaleAbs(yuan_x_64)#转换为给对值,负数转换为正数
cv2.imshow('yuan_x_full',yuan_x_full)
cv2.waitKey(0)
原图:

ddepth:输出图像的深度(可以理解为数据类型),-1表示与原图像相同的深度yuan_x=cv2.Sobel(yuan,-1,dx=1,dy=0)得到的图像

cv2.Sobel(yuan,cv2.CV_64F,dx=1,dy=0):cv2.CV_64F:因为梯度可能为负数(比如从亮到暗),用 64 位浮点型可以保留负数值,避免信息丢失得到的图像

cv2.convertScaleAbs(yuan_x_64):将负梯度值转为绝对值得到的图像

代码:用y方向的导数阶数
# #y方向上的边缘
yuan_y =cv2.Sobel(yuan,-1,dx=0,dy=1)
cv2.imshow('yuan_y',yuan_y)
cv2.waitKey(0)
#y方向上的边缘,包括负数信息(下端),但显示不出来,因为范围是(0~255)
yuan_y_64=cv2.Sobel(yuan,cv2.CV_64F,dx=0,dy=1)#默以int8改为fLoat64,可保存负数
yuan_y_full=cv2.convertScaleAbs(yuan_y_64)#转换为绝对值,负数转换为正数
cv2.imshow('yuan_y_full',yuan_y_full)
cv2.waitKey(0)
得到的图像:

2.Scharr 算子
Scharr 算子是对 Sobel 算子的优化版本,核心特点是:
-
同样用于图像梯度(边缘)检测,原理和 Sobel 一致(计算 x/y 方向梯度);
-
针对 3x3 核做了权重优化,梯度计算更精准,边缘检测结果更清晰;
-
没有核大小的选择(固定 3x3),可以理解为 “高精度版 3x3 Sobel”。
zl =cv2.imread('2.png',cv2.IMREAD_GRAYSCALE)#Scharr_算子
# zl=cv2.cvtColor(zl,cv2.COLOR_BGR2GRAY)
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)
与sobel算子的用法差不多,这里还用了cv2.addWeighted(zl_x_full,1,zl_y_full,1,0)方法加权合并两张图像( Scharr 算子的 x 方向边缘图和 y 方向边缘图),最终得到同时包含水平和垂直边缘的完整边缘图像。

3.Laplacian
这是一种基于拉普拉斯算子的边缘检测方法,和之前讲的 Sobel/Scharr(一阶梯度)不同,它是二阶梯度算子,能直接检测出图像中所有方向的边缘
cv2.Laplacian(src, ddepth, ksize=1, scale=1,delta=0)
src:输入图像,可以是灰度图像,也可以是多通道的彩色图像
ddepth:输出图片的数据深度:
ksize:计算二阶导数滤波器的孔径大小,必须为正奇数,可选项
scale:缩放比例因子,可选项,默认值为1
delta:输出图像的偏移量,可选项,默认值为0
zl =cv2.imread('2.png',cv2.IMREAD_GRAYSCALE)
zl_lap =cv2.Laplacian(zl,cv2.CV_64F,ksize=3)
zl_lap_full=cv2.convertScaleAbs(zl_lap)#转换为绝对值,负数转换为正数
cv2.imshow('zl_lap_full',zl_lap_full)
cv2.waitKey(0)
得到的图像:

4.canny边缘检测
作用:它是一套完整的边缘检测流程,能得到更干净、更准确的边缘结果
Canny 检测的 4 个核心步骤
-
高斯模糊:先对图像去噪(解决噪声干扰边缘的问题);
-
计算梯度:用 Sobel 算子计算图像的梯度(幅度 + 方向),找到边缘候选点;
-
非极大值抑制:只保留梯度方向上的局部最大值(把宽边缘 “细化” 成单像素宽度);
-
双阈值筛选:用高低两个阈值过滤边缘 —— 高于高阈值的是确定边缘,低于低阈值的直接舍弃,介于两者之间的仅当和确定边缘相连时保留(大幅减少伪边缘)。
canny函数:cv2.Canny(image, threshold1, threshold2, apertureSize=3, L2gradient=False)
image:输入图像(灰度图最佳,彩色图也可但效率低)
threshold1:低阈值(通常设为高阈值的 1/2 或 1/3)
threshold2:高阈值(核心参数,需根据图像调整,常用 100-200)
apertureSize:计算梯度用的 Sobel 核大小(默认 3,奇数)
L2gradient:梯度计算方式:False(默认,L1 范数,速度快);True(L2 范数,精度高)
代码:
zl =cv2.imread('2.png',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)
得到的图像:

昇腾计算产业是基于昇腾系列(HUAWEI Ascend)处理器和基础软件构建的全栈 AI计算基础设施、行业应用及服务,https://devpress.csdn.net/organization/setting/general/146749包括昇腾系列处理器、系列硬件、CANN、AI计算框架、应用使能、开发工具链、管理运维工具、行业应用及服务等全产业链
更多推荐



所有评论(0)