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)

得到的图像:

相关推荐
NAGNIP8 小时前
一文搞懂深度学习中的通用逼近定理!
人工智能·算法·面试
冬奇Lab9 小时前
一天一个开源项目(第36篇):EverMemOS - 跨 LLM 与平台的长时记忆 OS,让 Agent 会记忆更会推理
人工智能·开源·资讯
冬奇Lab9 小时前
OpenClaw 源码深度解析(一):Gateway——为什么需要一个"中枢"
人工智能·开源·源码阅读
AngelPP13 小时前
OpenClaw 架构深度解析:如何把 AI 助手搬到你的个人设备上
人工智能
宅小年13 小时前
Claude Code 换成了Kimi K2.5后,我再也回不去了
人工智能·ai编程·claude
九狼13 小时前
Flutter URL Scheme 跨平台跳转
人工智能·flutter·github
ZFSS13 小时前
Kimi Chat Completion API 申请及使用
前端·人工智能
天翼云开发者社区14 小时前
春节复工福利就位!天翼云息壤2500万Tokens免费送,全品类大模型一键畅玩!
人工智能·算力服务·息壤
知识浅谈15 小时前
教你如何用 Gemini 将课本图片一键转为精美 PPT
人工智能
Ray Liang15 小时前
被低估的量化版模型,小身材也能干大事
人工智能·ai·ai助手·mindx