opencv(边缘检测)

一、边缘检测

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方向的导数阶数

python 复制代码
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方向的导数阶数

python 复制代码
# #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"。

python 复制代码
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

python 复制代码
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 个核心步骤

  1. 高斯模糊:先对图像去噪(解决噪声干扰边缘的问题);

  2. 计算梯度:用 Sobel 算子计算图像的梯度(幅度 + 方向),找到边缘候选点;

  3. 非极大值抑制:只保留梯度方向上的局部最大值(把宽边缘 "细化" 成单像素宽度);

  4. 双阈值筛选:用高低两个阈值过滤边缘 ------ 高于高阈值的是确定边缘,低于低阈值的直接舍弃,介于两者之间的仅当和确定边缘相连时保留(大幅减少伪边缘)。

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 范数,精度高)

代码:

python 复制代码
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)

得到的图像:

相关推荐
lizhenning872 小时前
语言模型与动词知识库协同创新
人工智能·语言模型·自然语言处理
明月照山海-2 小时前
机器学习周报三十一
人工智能·机器学习
木头程序员2 小时前
算摄像学的“算法-传感器”协同设计:重新定义光学极限
人工智能·数码相机·硬件工程
Aaron_9452 小时前
Skyvern:基于LLM和计算机视觉的浏览器自动化平台深度解析
人工智能·计算机视觉·自动化
丝斯20112 小时前
AI学习笔记整理(52)——大模型之Agent 智能体
人工智能·笔记·学习
. . . . .2 小时前
AI应用总览
人工智能
袁气满满~_~2 小时前
机器学习笔记
人工智能·深度学习·机器学习
kingmax542120082 小时前
工信部教育与考试中心AI证书归纳
人工智能·ai证书·以考促学
2501_941507942 小时前
【房屋建筑目标检测】基于Decoupled-Solo模型的建筑检测方法实现与优化_r50_fpn_1x_coco
人工智能·目标检测·计算机视觉