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增长破局圈.赵老师讲成交2 分钟前
只有把过程管好,结果才会出来。
大数据·人工智能·ai·创业创新
最强小杰8 分钟前
gpt-5.6-sol 频繁报 503 怎么办?区分容量熔断和限速 429 的排查方法 + 可复用 retry wrapper
java·人工智能·gpt·ai
天天代码码天天22 分钟前
我做了一个只有一个 EXE 的本地 Markdown 编辑器:lw.MD(简墨)
人工智能
AI的探索之旅25 分钟前
97 个 OpenCV 实例(七):SIMD 向量化,给像素处理装上涡轮增压
人工智能·opencv·计算机视觉
不可求~27 分钟前
用 AI 读论文别只看摘要:建立可追溯的证据链
人工智能·深度学习·机器学习
狙击主力投资工具28 分钟前
通达信软件手机app和电脑使用手册教程.内含160多个.mpv版使用手册
人工智能
飞翔的火箭弹29 分钟前
伊顿电力模块技术参数深度解析:AI算力时代高集成供配电方案选型参考
人工智能
今天AI了吗39 分钟前
Python 基础语法(一):常量、变量、输入输出与运算符
开发语言·数据库·人工智能·python·sql·深度学习·机器学习
Warren2Lynch41 分钟前
从提示词到架构:Visual Paradigm VPasCode AI 驱动更新完全指南
人工智能·架构
ZGIAI1 小时前
ZGI 发布治理:同一个 Agent 服务多个入口
人工智能·架构