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)

得到的图像:

相关推荐
岁岁种桃花儿几秒前
AI超级智能开发系列从入门到上天第七篇:PromptTemplate模板
人工智能·llm
code_pgf2 分钟前
Jetson Orin NX 16G部署openclaw及本地化安全配置及建议
人工智能·安全·ai
weixin_668898642 分钟前
RNN解读
人工智能
weixin_549808362 分钟前
从“人海战术“到“智能寻猎“:eRoad AI招聘系统的实战价值重构
人工智能·重构
Rubin智造社4 分钟前
# OpenClaw v26.3.22升级踩坑预警!飞书插件失效、建议暂缓升级让子弹飞一飞
人工智能·飞书·openclaw·小龙虾
AI英德西牛仔5 分钟前
ChatGPT和Gemini怎么导出文档
人工智能·ai·chatgpt·deepseek·ds随心转
纤纡.5 分钟前
基于 OpenCV 的计算机视觉实战:从图像矫正到指纹识别
人工智能·opencv·计算机视觉
北极九章ArcticData5 分钟前
销售管理团队如何用ChatBI实现数据驱动管理?
大数据·人工智能·数据分析·chatbi
chushiyunen6 分钟前
NLP动态切片、静态切片、拆分
人工智能·自然语言处理·easyui
果粒蹬i7 分钟前
自建私有仪表盘:Dashlet 部署与公网访问全教程
人工智能·编辑器