十五、计算机视觉-sobel算子

文章目录

  • 前言
  • 一、sobel算子的概念
  • 二、sobel算子的计算方式
  • 三、具体实现


前言

上节课我们学习了梯度的知识,学习了如何去计算梯度,本节我们继续学习计算梯度的方法,本节我们学习使用Sobel算子计算梯度,这与上节课梯度计算方法有所不同,一般如果需要准确地计算图像的梯度信息,特别是对边缘信息感兴趣,通常会选择Sobel、Scharr或Laplacian算子。而如果更关注形态学特征或者想要一种简单快速的边缘检测方法,可以考虑使用cv2.morphologyEx。

一、sobel算子的概念

Sobel算子是一种用于图像边缘检测的经典算法。它基于一种称为梯度的数学概念,用于找到图像中灰度变化较大的地方,通常表现为图像中的边缘或轮廓。
Sobel算子通过在图像上应用两个3×3的卷积核(或称为模板)来计算图像的梯度,这两个卷积核分别用于检测图像中水平和垂直方向的变化。
这些卷积核的设计是为了捕捉图像中的灰度变化,使得在卷积过程中离边缘更近的像素权重更大,从而突出边缘特征。通过计算图像中每个像素点的水平和垂直方向的梯度,Sobel算子能够有效地检测图像中的边缘。

二、sobel算子的计算方式

上面提到sobel算子是通过一个3x3的卷积核来计算图像梯度,卷积核我们前面已经有过了解了。在这里卷积核是什么内容呢?
我们首先看下Sobel算子的计算公式:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
sobel算子包括两个3×3的卷积核,分别用于计算图像在水平和垂直方向上的梯度。
Gx是水平方向的梯度,Gy是垂直方向的梯度,最终2个值的绝对值相加就是最终的梯度结果。
这2个卷积核的内容如下:
在这里插入图片描述
我们来分析一下这个公式:卷积核内容为什么要这样设置,以及这个公式为什么这样计算,有什么底层的逻辑。
首先我们看下横向梯度的计算方式,假如卷积核覆盖的图像像素点如下:

在这里插入图片描述
那结合上面的横向卷积核的内容 他的计算公式为:(p3-p1)+(2p6-2p4)+(p9-p7).
而卷积核的内容实际上是代表的权重。比如离中心点越近权重越高。因为我们目的是进行边缘检测,而边缘通常指的是图像中灰度变化较大的地方,而像素值的变化通常发生在边缘附近。通过将离中心点最近的像素的权重设置为2或-2,可以加大边缘处灰度变化对卷积结果的影响,从而更好地突出边缘特征。如下图:(实际卷积核不是图示这么大 图只是为了方面演示查看)
和之前课程中讲到的卷积核一样,卷积核在图像上移动
在这里插入图片描述
当我么卷积核范围没有灰度变化时,通过公式计算就没有产生梯度,一旦当卷积核范围产生了灰度变化 比如
在这里插入图片描述
通过上面公式我们计算卷积核中心点位置 也就是图像p5的位置 就有值了。
当卷积核在移动到没有灰度变化的地方 就不会产生梯度
在这里插入图片描述
现在有个问题:当卷积核移动到图像右边边缘时

在这里插入图片描述
按照我们的计算公式,右边减左边,在这个位置右边减左边肯定是小于0了,默认opencv处理是小于0的就置为0 但是我们右边也有边缘置为0就是看不到边缘了,不符合我们的要求了,那怎么办呢。在回到上面的公式
在这里插入图片描述
这就是我们使用绝对值的原因。

纵向方向的梯度和横向方向的梯度原理都是一样的,只不过纵向方向的是下面的减去上面的
(p9-p3)+(2p8-2p2)+(p7-p1)。通过纵向计算同样得到一个边缘。2个边缘相加就是我们的最终结果。纵向这里就不在演示了。那有人可能问了,我们为什么要分别计算纵向和横向,既然纵向和横向都可以获取边缘信息,我们为何不只使用其中一种方式,或者2种方式同时使用,而不是单独计算在相加?
其实你自己实际测试一下就知道原因了,这种方式可以更好地捕捉图像中的边缘信息。虽然理论上可以设计一个3×3的卷积核同时计算水平和垂直方向的梯度,但在实践中,分别计算水平和垂直方向的梯度更为常见且更有效。分别计算水平和垂直方向的梯度可以提供更多的方向信息,使得边缘检测更加准确。例如,当图像中的边缘是斜向的时候,水平和垂直方向的梯度可以更好地捕捉到这种特征。

三、具体实现

import cv2

# 读取图像
image = cv2.imread('yunfeng.jpg')

# 转换为灰度图像
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 使用Sobel算子计算水平方向和垂直方向的梯度
grad_x = cv2.Sobel(gray_image, cv2.CV_64F, 1, 0, ksize=3)
grad_y = cv2.Sobel(gray_image, cv2.CV_64F, 0, 1, ksize=3)

# 计算梯度的幅值
gradient_magnitude = cv2.magnitude(grad_x, grad_y)

# 显示结果
cv2.imshow('Original', image)
cv2.imshow('sobel', cv2.convertScaleAbs(gradient_magnitude))

cv2.waitKey(0)
cv2.destroyAllWindows()

其中cv2.Sobel是计算梯度信息,cv2.Sobel(gray_image, cv2.CV_64F, 1, 0, ksize=3)
第一个参数是输入的图片信息,
第二个参数是图像数据类型,Sobel算子的计算中,我们通常会使用CV_64F作为数据类型,以便在计算过程中保持足够的精度。64位浮点数格式可以处理更大范围的数值,以及更高的精度,有助于避免在计算过程中出现数值溢出或失真的情况
第三个参数是1代表计算横向的梯度
第四个参数是0代表不计算纵向的梯度
第五个参数是卷积核大小

cv2.magnitude就是我们上面提到的公式的实现方法
在这里插入图片描述
我们看下最终的结果
在这里插入图片描述
在这里插入图片描述


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/461122.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ARMv8架构特殊寄存器介绍-0

一、zero 寄存器 零寄存器用作源寄存器时读取零,用作目标寄存器时丢弃结果。您可以在大多数指令中使用零寄存器,但不是所有指令。二、sp寄存器 在ARMv8架构中,要使用的堆栈指针的选择在某种程度上与Exception级别。默认情况下,异…

大数据Doris(六十九):项目线上表现

文章目录 项目线上表现 一、查询响应时间

java学习之路-程序逻辑控制

目录 1.分支结构 1.1 if语句 栗子 判断奇数还是偶数 判断一个年份是否为闰年 1.2switch语句 栗子 2. 循环结构 2.1while 循环 栗子 2.2break和continue break continue 2.3for循环 基本语法 栗子 2.4 do while 循环 3.输入输出 3.1输出 3.2从键盘输入 栗子…

基于FPGA的光纤通信系统的实现的优化技巧与方法

逻辑电路基本框架回顾 跨时钟域同步技术 读写操作相互独立时钟域 A 和 B 不需要一致的相位由专门逻辑控制读写操作的切换 高速数据的乒乓缓存技术

SimpleDateFormat类 --java学习笔记

SimpleDateFormat 代表简单日期格式化,可以用来把日期对象、时间毫秒值格式化成我们想要的形式 常见构造器和方法: pattern 代表需要应用的时间格式—— 时间格式的常见符号: 时间格式的应用举例: import java.text.SimpleDate…

集合系列(二) -List接口详解

一、List简介 List 的数据结构就是一个序列,存储内容时直接在内存中开辟一块连续的空间,然后将空间地址与索引对应。 以下是List集合简易架构图 由图中的继承关系,可以知道,ArrayList、LinkedList、Vector、Stack都是List的四个…

【计算机网络】UDP/TCP 协议

TCP 协议 一、传输层1. 再谈端口号2. 端口号范围划分3. 进程和端口号4. netstat5. pidof 二、UDP 协议1. UDP 协议端格式(报文)2. UDP 的特点3. 面向数据报4. UDP 的缓冲区 三、TCP 协议1. 认识 TCP2. TCP 协议段格式(1)4 位首部长度(2&#…

Android U pipeline-statusbar

Android U - statusbar pipeline 写在前面 Android原生从T开始对SystemUI进行MVVM改造,U上状态栏部分进行了修改;第一次出现修改不会删除原有逻辑,而是两版并行,留给其他开发者适配的时间;在下一个大版本可能会删除原…

Java获取视频封面图,利用FFmpegFrameGrabber获取视频封面图

依赖 <dependency><groupId>org.bytedeco</groupId><artifactId>javacv-platform</artifactId><version>1.5.9</version></dependency>传入视频流获取图片byte /*** 获取视频截图** param frameNumber 视频的指定帧数* param …

Ubuntu查看ros版本-linux查看ros版本

使用ros带的rosversion命令即可查看自己的ros版本&#xff1a; rosversion -d

双指针算法_复写零

题目&#xff1a; 给一个固定长度的数组arr&#xff0c;将数组中出现的每一个0都复写一遍&#xff0c;并且将其余元素都往右移动 且不要再超过数组长度的位置写入元素&#xff0c;在数组上直接修改 示例&#xff1a; 双数组模拟操作&#xff1a; 从示例来看&#xff0c;因为…

Linux 中搭建 主从dns域名解析服务器

CSDN 成就一亿技术人&#xff01; 作者主页&#xff1a;点击&#xff01; Linux专栏&#xff1a;点击&#xff01; CSDN 成就一亿技术人&#xff01; ————前言———— 主从&#xff08;Master-Slave&#xff09;DNS架构是一种用于提高DNS系统可靠性和性能的配置方式。…

视频素材在哪里找?5个无版权视频素材网站

今天我再给大家介绍几个视频素材在哪里找&#xff0c;希望能帮你的短视频创作更加顺手&#xff1a; 蛙学网&#xff1a; 蛙学网是国内的一个视频素材平台&#xff0c;适合做短视频的朋友。这里的素材非常多&#xff0c;涵盖了各种风格和主题。更新速度也很快&#xff0c;能够帮…

Java多线程实战-异步操作日志记录解决方案(AOP+注解+多线程)

&#x1f3f7;️个人主页&#xff1a;牵着猫散步的鼠鼠 &#x1f3f7;️系列专栏&#xff1a;Java全栈-专栏 &#x1f3f7;️本系列源码仓库&#xff1a;多线程并发编程学习的多个代码片段(github) &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正…

Python笔记|字符串的转义

重新梳理一遍python的基础知识 除了数字&#xff0c;Python 还可以操作字符串。字符串有多种表现形式&#xff0c;用单引号&#xff08;……&#xff09;或双引号&#xff08;"……"&#xff09;标注的结果相同 。反斜杠 \ 用于转义&#xff1a; >>>spam e…

QT网络编程之实现TCP客户端和服务端

推荐一个不错的人工智能学习网站&#xff0c;通俗易懂&#xff0c;内容全面&#xff0c;作为入门科普和学习提升都不错&#xff0c;分享一下给大家&#xff1a;前言https://www.captainbed.cn/ai 一.QT5.12实现TCP客户端和服务端功能 1.QT中实现TCP通信主要用到了以下类&…

weblogic CVE-2023-21839详细复现

1、本次复现使用vulhub的靶场 切换到靶场的目录下&#xff0c;用docker -compose up -d启动靶场 使用docker-compose ps -a查看靶场的端口 2、访问开启的环境 3、准备工作都做好之后开始复现 &#xff08;1&#xff09;开启JNDIExploit 工具地址&#xff1a;GitHub - WhiteH…

拌合楼内部管理系统开发(一)立个flag,开始做准备

前言&#xff1a;项目背景情况介绍 公司有意开发一套适合拌合楼的内部管理系统给到客户使用&#xff0c;接触过一家拌合楼行业内号称标杆的企业&#xff0c;去过参观学习的都觉得他们软件好用&#xff0c;但是从软件开发角度看&#xff0c;就是crud钉钉机器人无人值守。虽然公司…

开源绘图工具 PlantUML 入门教程(常用于画类图、用例图、时序图等)

文章目录 一、类图二、用例图三、时序图 一、类图 类的UML图示 startuml skinparam classAttributeIconSize 0 class Dummy {-field1 : String#field2 : int~method1() : Stringmethod2() : void } enduml定义能见度&#xff08;可访问性&#xff09; startumlclass Dummy {-f…

基于ssm+layui的图书管理系统

基于ssmlayui的图书管理系统 账户类型分为&#xff1a;管理员&#xff0c;用户管理员私有功能用户私有功能公共功能技术栈功能实现图 视频演示 账户类型分为&#xff1a;管理员&#xff0c;用户 图书管理系统主要登录账户类型为管理员账户与用户账户 管理员私有功能 账户管理…
最新文章