当前位置: 首页 > news >正文

(纯新手教学)计算机视觉(opencv)实战七——边缘检测Sobel 算子(cv2.Sobel())详解

更多学习:四种边缘检测

(纯新手教学)计算机视觉(opencv)实战八——四种边缘检测详解:Sobel、Scharr、Laplacian、Canny-CSDN博客https://blog.csdn.net/2302_78022640/article/details/150592942?sharetype=blogdetail&sharerId=150592942&sharerefer=PC&sharesource=2302_78022640&spm=1011.2480.3001.8118


边缘检测

1. 边缘检测的概念

在图像处理中,**边缘(Edge)**是像素灰度值急剧变化的区域,通常对应图像中的物体边界、纹理或者结构特征。检测边缘有助于我们提取图像的几何结构,广泛应用于物体识别、分割和计算机视觉任务。

最常见的边缘检测方法之一就是 Sobel 算子


2. Sobel 算子的基本原理

Sobel 算子通过计算图像在 水平方向(x)垂直方向(y) 的梯度,来检测图像的边缘。

  • 梯度(Gradient):反映灰度值变化的快慢,变化越大说明该区域越可能是边缘。

  • Sobel 算子在计算时,会结合平滑微分操作,减少噪声干扰。

其常见的卷积核为:

  • 水平方向(x方向)核

  • 垂直方向(y方向)核

通过与图像进行卷积,分别得到 x方向梯度y方向梯度,再进行组合就能得到最终的边缘。


3. cv2.Sobel() 函数

在 OpenCV 中,Sobel 算子的函数为:

cv2.Sobel(src, ddepth, dx, dy[, ksize[, scale[, delta[, borderType]]]])

参数说明:

参数说明
src输入图像(一般用灰度图像)
ddepth输出图像的深度。常用 cv2.CV_64F,避免数据溢出
dxx方向的差分阶数(1 表示一阶导数)
dyy方向的差分阶数(1 表示一阶导数)
ksizeSobel 核大小,必须是 1, 3, 5, 7(常用 3)
scale可选参数,缩放导数值
delta可选参数,结果加上某个值
borderType边界填充方式,默认 cv2.BORDER_DEFAULT

4. 代码解析与效果

可直接使用下图,也可自备图片:但是要记得灰度处理(根据需要也可以尝试彩色)

所有处理后的结果:

(1)读取与显示图像

import cv2
img = cv2.imread('violet.jpg',cv2.IMREAD_GRAYSCALE)
img = cv2.resize(img,(800,500))
cv2.imshow('img', img)
cv2.waitKey(0)
  • 使用灰度图像,便于边缘提取。

  • 图像缩放到合适大小,便于展示。


(2)x方向的边缘

# x方向上的边缘
img_x = cv2.Sobel(img, -1, dx=1, dy=0)
cv2.imshow('img_x', img_x)
cv2.waitKey(0)
  • 这里 dx=1, dy=0,表示只计算水平方向的梯度。

  • 能突出 竖直边缘(例如物体左右边界)。

  • 使用 -1 表示输出图像深度与原图相同。


(3)保留负值信息

# x方向上的边缘,包含负值信息(直接显示不出来,因为范围是0~255)
img_x_64 = cv2.Sobel(img, cv2.CV_64F, dx=1, dy=0)  # 默认uint8改为float64, 可保存负数
cv2.imshow('img_x_64', img_x_64)
cv2.waitKey(0)
  • cv2.CV_64F 可保存浮点数,包括正负值。

  • 因为梯度可能是正数(亮到暗的变化)或负数(暗到亮的变化)。

  • 但直接显示会出现“黑屏”,因为显示范围是 0~255


(4)转换为可视化图像

# x方向上的边缘,将负数的数值信息转成可视化的数值,右端的负值信息就能显示出来了
img_x_full = cv2.convertScaleAbs(img_x_64)  # 转换为绝对值,负数转换为正数
cv2.imshow('img_x_full', img_x_full)
cv2.waitKey(0)
  • 将梯度的负值转换为绝对值,保证显示效果。

  • 这样左右边界都能显示出来。


(5)y方向的边缘

# y方向的边缘
img_y = cv2.Sobel(img, -1, dx=0, dy=1)
cv2.imshow('img_y', img_y)
cv2.waitKey(0)# y方向上的边缘,包括负数信息(下端),但是示不出来,因为范围是(0~255)
img_y_64= cv2.Sobel(img,cv2.CV_64F,dx=0,dy=1)#默认int8改为float64,可保存负数
img_y_full = cv2.convertScaleAbs(img_y_64)#转换为绝对值,负数转换为正数
cv2.imshow( 'img_y_full',img_y_full)
cv2.waitKey(0)
  • dx=0, dy=1,表示只计算垂直方向的梯度。

  • 能突出 水平边缘(例如物体上下边界)。

同样地,可以通过 cv2.CV_64F + cv2.convertScaleAbs 来显示完整信息。


(6)直接同时计算 x 和 y

# 同时使用x与y方向的边缘(不建议直接使用!!)
img_xy = cv2.Sobel(img, -1, dx=1, dy=1)
cv2.imshow('img_xy', img_xy)
cv2.waitKey(0)
  • 这种方式会将 x 和 y 梯度直接结合,但通常效果不佳,不推荐。


(7)分别计算x和y后,加权融合

# 使用图像加权运算组合x和y方向的2个边缘
img_xy_full = cv2.addWeighted(img_x_full,1,img_y_full,1,0)
cv2.imshow('img_xy_full', img_xy_full)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • 更合理的方式是把 x方向y方向 的梯度结果加权融合。

  • addWeighted 会线性叠加两张图像。

  • 得到的结果类似于常见的 梯度幅值图像,即完整的边缘检测效果。


5. 总结

  1. Sobel 算子利用梯度变化检测边缘,能提取水平与垂直方向上的特征。

  2. 使用 cv2.CV_64F 保留负值信息,再通过 cv2.convertScaleAbs 转换为可视化结果。

  3. x方向突出竖直边缘,y方向突出水平边缘。

  4. 最佳实践是分别提取 x、y 梯度,然后再融合,得到更清晰的边缘图像。


📌 扩展:除了 Sobel 算子,常用的边缘检测方法还有 Prewitt 算子、Laplacian 算子、Canny 算子,各有优劣,Canny 是实际应用最广的。

http://www.dtcms.com/a/343739.html

相关文章:

  • ⭐CVPR2025 无约束 3D 视线估计新框架[特殊字符]
  • 【图像算法 - 21】慧眼识虫:基于深度学习与OpenCV的农田害虫智能识别系统
  • Python opencv识别图片中重叠圆的圆心位置
  • 焊接工艺仿真软件SYSWELD、Simufact.Welding和FLOW-3D WELD的区别
  • 【0基础3ds Max】捕捉工具详解
  • 城市生命线地下管网三维建模软件MagicPipe3D更新历史
  • ZBrush和3D-Coat如何实现快速桥接?
  • `git mv` 重命名 Git 仓库中的文件夹
  • OFSP路由与传输层协议
  • LLM实践系列:利用LLM重构数据科学流程
  • 亚矩阵云手机:亚马逊第三方店铺多账号安全合规运营的核心技术支撑
  • 代码随想录Day59:图论(最短路算法dijkstra堆优化版精讲、Bellman_ford 算法精讲)
  • 【生成树+环】题解:P3907 环的异或_图论_环_异或_搜索_算法竞赛_C++
  • 【typenum】 22 类型级别二进制对数运算(Logarithm2)
  • Apache Ozone 介绍与部署使用(最新版2.0.0)
  • Vue2+Vue3前端开发_Day6
  • Spring-AI初级使用记录 spring-ai-bom版本1.0.1-(单、多轮对话)
  • reactive 核心要点
  • FFmpeg及 RTSP、RTMP
  • 大型前端项目如何实现css 隔离:利用浏览器原生的 Shadow DOM 完全隔离 DOM 结构与样式...
  • 前端AI工具——TRAE
  • Linux基础命令大全:从入门到熟练
  • 开发避坑指南(34):mysql深度分页查询优化方案
  • GitCode 疑难问题诊疗:全面指南与解决方案
  • 关于在 IntelliJ IDEA 中安装和配置 Java 17
  • 简单聊聊多模态大语言模型MLLM
  • RabbitMQ 应用问题
  • RabbitMQ深度剖析:从基础到高级进阶实战
  • RabbitMQ 全面指南:架构解析与案例实战
  • 线性回归学习笔记