《图像梯度与常见算子全解析:原理、用法及效果展示》

简介:本文深入探讨图像梯度相关知识,详细介绍图像梯度是像素灰度值在不同方向的变化速度,并以 “pig.JPG” 图像为例,通过代码展示如何选取图像部分区域并分析其像素值以论证图像梯度与边缘信息的关联。接着全面阐述了 Sobel 算子,包括 ddepth 参数对边缘检测完整性的影响及 dx、dy 参数不同设置的效果差异;Scharr 算子的用法及其相较于 Sobel 算子在准确度上的优势;Laplacian 算子的特性,如在检测微小细节变化方面的优势、对噪声敏感及需先平滑处理的要点,并给出了各算子在图像边缘检测应用中的代码示例与实际效果展示,助力读者深入理解图像梯度与相关算子在图像处理中的作用。
如果本文对你的图像梯度学习有所帮助,请给我点赞收藏关注,我会为你持续提供与OpenCV学习相关的文章。
《图像梯度与常见算子全解析:原理、用法及效果展示》
- 图像梯度
- 什么是图像梯度?
- sobel算子
- ddepth的用法
- dx dy参数设置(请记住这里有两个知识点)
- Scharr算子
- Laplacian算子(三个知识点)
- 致谢
图像梯度
什么是图像梯度?
它是指像素灰度值在不同方向的变化速度。我通过OpenCV的代码把这张命名为pig.JPG的图像选择出一部分,给大家展示一下。
这是我项目的文件结构:

需要图片的可以直接复制,我把他放到文章里了

我用代码选择出猪猪侠的偏底部的部分展示一下
import numpy as np
import cv2
image = cv2.imread("pig.JPG")
print(image.shape)
image = image[800:850,229:250]
cv2.imshow("image",image)
cv2.waitKey()
cv2.destroyAllWindows()

我们现在已经把这个猪猪侠的腿部选出来了,我们去打印它的np像素值
import numpy as np
import cv2
image = cv2.imread("pig.JPG")
image = image[800:850,229:250]
print(image)

我们可以看到灰度值从几十变成一两百差别很大,而图片中的内容恰好对应的是腿部的轮廓。说明梯度变化大的时候针对的就是轮廓。一切都是为了论证这句话:一般情况下,图像梯度计算的是图像的边缘信息
再通过我用画图板画的一张图来证明一下(画的简陋多多包涵):

水平方向同理,请看下图:

sobel算子
语法 :
dst = cv2.Sobel(原始图像src,ddepth图像深度,dx 计算水平方向的偏导数 ,dy 计算垂直方向的偏导数,ksize算子大小)
因为不同的参数影响很大,所以要一个一个参数的用法讲
ddepth的用法
比如说我在画图板画出下面这个图,命名为so_1.JPG ,设置图像深度为 0 就是与原图像一致,ksize = 3 dx =1 dy =0

import numpy as np
so_1_img = cv2.imread("so_1.JPG",cv2.IMREAD_GRAYSCALE)
dst = cv2.Sobel(so_1_img,ddepth = 0,dx = 1,dy = 0,ksize = 3)
cv2.imshow('original',so_1_img)
cv2.imshow("sob",dst)
cv2.waitKey()
cv2.destroyAllWindows()

你观察图片可以发现,他只找到了一条的边,可是这个方向的边应该有两条。原因是因为白色是255,黑色是0 白右黑左的时候差值为255,而白左黑右的时候-255,被自动忽略了。
要解决这种方式需要提高ddepth,然后对计算结果取绝对值,因为我读入图片的时候选择的是八位灰度值的,所以我在使用sobel算子可以设置为64位,然后再使用cv2.convertScaleAbs()对图片取绝对值然后就可以出现两条边了。请看下面的代码:
import numpy as np
so_1_img = cv2.imread("so_1.JPG",cv2.IMREAD_GRAYSCALE)
dst = cv2.Sobel(so_1_img,ddepth = cv2.CV_64F,dx = 1,dy = 0,ksize = 3)
ddst = cv2.convertScaleAbs(dst)
cv2.imshow('original',so_1_img)
cv2.imshow("sob",dst)
cv2.imshow("abs_sob",ddst)
cv2.waitKey()
cv2.destroyAllWindows()

dx dy参数设置(请记住这里有两个知识点)
第一个知识点 设置一者为1 另一者为0可以计算单独方向的轮廓,如果想同时计算那么需要二者使用cv2.addweighted函数一者0.5对水平和竖直方向进行加权。
还是拿同一张图展示:
import numpy as np
so_1_img = cv2.imread("so_1.JPG",cv2.IMREAD_GRAYSCALE)
dst = cv2.Sobel(so_1_img,ddepth = cv2.CV_64F,dx = 1,dy = 0,ksize = 3)
ddst = cv2.convertScaleAbs(dst)
y_dst = cv2.Sobel(so_1_img,ddepth = cv2.CV_64F,dx = 0,dy = 1,ksize = 3)
y_ddst = cv2.convertScaleAbs(y_dst)
add = cv2.addWeighted(ddst,0.5,y_ddst,0.5,0)
cv2.imshow('original',so_1_img)
cv2.imshow("abs_x_sob",ddst)
cv2.imshow("abs_y_sob",y_ddst)
cv2.imshow("add",add)
cv2.waitKey()
cv2.destroyAllWindows()

第二个知识点是,同时设置dx =1 dy =1与第一个知识点的计算结果并不一致,因为
图像中的边缘并不总是简单的水平或垂直方向。在实际的图像中,边缘可能是倾斜的、弯曲的或者有噪声干扰。
当分别计算和方向梯度并加权相加时,可能会丢失一些复杂边缘的细节信息。而dx = 1、dy = 1的计算方式会以一种不同的角度来捕捉这些复杂边缘的变化,包括对角边缘等,所以结果会和简单加权相加的情况不一致。
我们拿猪猪侠这张图来验证一下
import numpy as np
so_1_img = cv2.imread("pig.JPG",cv2.IMREAD_GRAYSCALE)
dst = cv2.Sobel(so_1_img,ddepth = cv2.CV_64F,dx = 1,dy = 0,ksize = 3)
ddst = cv2.convertScaleAbs(dst)
y_dst = cv2.Sobel(so_1_img,ddepth = cv2.CV_64F,dx = 0,dy = 1,ksize = 3)
y_ddst = cv2.convertScaleAbs(y_dst)
add = cv2.addWeighted(ddst,0.5,y_ddst,0.5,0)
x_y_dst = cv2.Sobel(so_1_img,ddepth = cv2.CV_64F,dx = 1,dy =1,ksize = 3)
x_y_ddst = cv2.convertScaleAbs(x_y_dst)
cv2.imshow('original',so_1_img)
cv2.imshow("add",add)
cv2.imshow("dxdy11",x_y_ddst)
cv2.waitKey()
cv2.destroyAllWindows()

Scharr算子
用法与sobel一样就是函数名不一样 cv2.Scharr(),有两个区别就是
- scharr没有ksize这个参数。
- scharr不能同时设置dx dy为1
他比sobel算子准确度更高,是一种改良,我们还用pig.JPG来展示:
import numpy as np
so_1_img = cv2.imread("pig.JPG",cv2.IMREAD_GRAYSCALE)x_y_dst = cv2.Sobel(so_1_img,ddepth = cv2.CV_64F,dx = 1,dy =1,ksize = 3)
x_y_ddst = cv2.convertScaleAbs(x_y_dst)x_scharr = cv2.Scharr(so_1_img,ddepth = cv2.CV_64F,dx = 1,dy =0)
x_sscharr = cv2.convertScaleAbs(x_scharr)y_scharr = cv2.Scharr(so_1_img,ddepth = cv2.CV_64F,dx = 0,dy =1)
y_sscharr = cv2.convertScaleAbs(y_scharr)x_y_sscharr = cv2.addWeighted(x_sscharr,0.5,y_sscharr,0.5,0)cv2.imshow('original',so_1_img)
cv2.imshow("dxdy11",x_y_ddst)
cv2.imshow("scharr",x_y_sscharr)
cv2.waitKey()
cv2.destroyAllWindows()

明显看出来后者抓住了更多轮廓,下过更好
Laplacian算子(三个知识点)
第一个知识点: 相比于sobel算子,Laplacian 算子在检测一些微小的细节变化(如噪点引起的小波动或者很细的线条)方面可能更有优势。
第二个知识点:由于 Laplacian 算子是二阶导数,它对噪声比较敏感。在图像存在噪声时,噪声点周围的像素值变化会被 Laplacian 算子放大,可能导致误检测出许多假边缘。所以在实际应用中,通常会先对图像进行平滑处理(如使用高斯滤波),然后再应用 Laplacian 算子进行边缘检测,以减少噪声的影响。
第三个知识点,他的语法:
dst = cv2.Laplacian(原始图像src,图像深度ddepth,ksize核尺寸大小,scale缩放因子,delta计算结果+delta说白了就是个附加值,borderType就是个边界样式一般不用修改)
还用pig.JPG这个图片做例子:
import numpy as np
import cv2
img = cv2.imread("pig.JPG",cv2.IMREAD_GRAYSCALE)
lap = cv2.Laplacian(img,cv2.CV_64F)
lap = cv2.convertScaleAbs(lap)
cv2.imshow("original",img)
cv2.imshow("laplacian",lap)
cv2.waitKey()
cv2.destroyAllWindows()

致谢
本文参考了一些博主的文章,博取了他们的长处,也结合了我的一些经验,对他们表达诚挚的感谢,使我对 图像梯度与算子 有更深入的了解,也推荐大家去阅读一下他们的文章。纸上学来终觉浅,明知此事要躬行:
OpenCV图像处理(十一)—图像梯度
一文讲解图像梯度
相关文章:
《图像梯度与常见算子全解析:原理、用法及效果展示》
简介:本文深入探讨图像梯度相关知识,详细介绍图像梯度是像素灰度值在不同方向的变化速度,并以 “pig.JPG” 图像为例,通过代码展示如何选取图像部分区域并分析其像素值以论证图像梯度与边缘信息的关联。接着全面阐述了 Sobel 算子,…...
【c++篇】:探索c++中的std::string类--掌握字符串处理的精髓
✨感谢您阅读本篇文章,文章内容是个人学习笔记的整理,如果哪里有误的话还请您指正噢✨ ✨ 个人主页:余辉zmh–CSDN博客 ✨文章所属专栏:c篇–CSDN博客 文章目录 前言一.std::string对象的创建二.std::string对象的访问三.std::str…...
LlamaIndex ollama 搭建本地RAG应用,建立本地知识库
目录 简介安装前的准备下载ollama创建llamaindex conda环境,为后面编码作准备 环境变量迁移ollama到其他盘运行ollama方式一方式二禁止ollama开机自启动运行第一个模型 Chatbox聊天下载Chatbox配置ollama地址和模型验证 建立自身特定知识数据搭配大语言模型创建项目…...
draggable的el-dialog实现对话框标题可以选择
请看图 这个对话框使用了el-dialog并且draggable属性设置成了true,所以标题栏这里就可以拖动,现在用户想选中标题栏的文本进而复制。我看到这个需求头都大了。 我能想到的方案有三个:1. 取消draggable为true 2. 标题文案后面加一个复制按钮 …...
2024年Android面试总结
2024年Android面试总结 1.动画类型有哪些?插值器原理? 2.StringBuffer和StringBuilder区别? 3.jvm内存模型? 4.线程池7大核心参数及原理? 5.Android多进程通信方式有哪些?各自的优缺点? 6…...
树莓派3:64位系统串口(UART)使用问题的解决方法
前言 当我们要使用串口进行zigbee的短距离通信时,发现无法使用串口. 原因 树莓派3bCPU内部有两个串口,一个硬件串口(就是我们平时使用的UART),还有一个迷你串口(mini-uart),在老版本的树莓派中把硬件串口分配在GPIO上,可以单独使用.但是在新的树莓派中官方把硬件串口给了蓝牙…...
SemiDrive E3 硬件设计系列---唤醒电路设计
一、前言 E3 系列芯片是芯驰半导体高功能安全的车规级 MCU,对于 MCU 的硬件设计部分,本系列将会分模块进行讲解,旨在介绍 E3 系列芯片在硬件设计方面的注意事项与经验,本文主要讲解 E3 硬件设计中唤醒电路部分的设计。 二、RTC 模…...
淘宝接口高并发采集核心要点解读,开启电商数据智能应用新纪元
一、引言 在电商蓬勃发展的今天,淘宝作为全球知名的电商巨头,其平台上的数据犹如一座蕴藏无限价值的宝藏。准确且高效地采集淘宝接口数据,并通过高并发技术实现大规模数据获取,对于电商企业的精准营销、市场趋势分析、竞品监测以及…...
C#里怎么样快速使用LINQ实现查询?
C#里怎么样快速使用LINQ实现查询? 在C#里使用LINQ,是一个方便的功能, 不过,要学会使用这部分的功能,需要比较多的学习时间,否则,使用起就比较难。 因为它的表现方式,与编程语言通用的功能,还是差别比较大。 当数据量比较小,没有特定的顺序时,使用LINQ访问会比较好…...
2024新版微软edge浏览器输入百度网址时自动补全tn=68018901……小尾巴的解决
以前一直是Windows11 21h2版本,浏览器内输入baidu不会自动补全tnxx的百度推广小尾巴。然后前几天在BIOS内开启了tpm2.0,升级Windows11到了24h2版本。 发现在edge浏览器内只要输入b,就会自动补全为baidu.com?tnXXX的这么一个百度推广形式。开…...
uni-app打包H5自定义微信分享
1、配置分享信息 修改uni-app的index.html,添加Open Graph(OG)标签来配置分享信息。 <!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8" /><meta name="description" content="标题"/>…...
大模型专栏--大模型应用场景
紧接着第一篇,什么是大模型,这篇文章讨论一下大模型的应用场景和应用方式有哪些? 基础使用 随着 GPT 的出现,AI 大模型已经越来越多得出现在日常生活和学术研究,工作中。 按照使用方向有以下几种: 自然语…...
骑砍2霸主MOD开发(29)-顶点动画
一.定制化顶点动画(MorphAnimation) 定制化顶点动画用于人物Agent的面部表情. 1.创建MorphAnimation对应静态资源morph_animation.tpac 2.Agent设置对应MorphAnimation [EngineMethod("set_agent_facial_animation", false)] void SetAgentFacialAnimation(UIntPtr …...
-Dspring.profiles.active=dev与--spring.profiles.active=dev的区别
在Spring Boot应用程序中,-Dspring.profiles.activedev和--spring.profiles.activedev都用于指定要激活的Spring配置文件(profile),但它们在不同的环境中使用,并且有不同的作用域。 -Dspring.profiles.activedev&#…...
面向对象高级(2)单例设计对象与代码块
面向对象高级(2) 单例设计模式、main方法与代码块 引言; 设计模式:特定环境下特定问题的处理方法。可理解为一种经典的可以参照的模板。单例设计模式则是只存在单个对象实例、且只有一种方法获取对象实例的一种设计模式。 单例设…...
47小型项目的规划与实施
每天五分钟学Linux | 第四十七课:小型项目的规划与实施 大家好!欢迎再次来到我们的“每天五分钟学Linux”系列教程。在前面的课程中,我们学习了并发编程的知识,包括如何管理和使用进程与线程。今天,我们将探讨如何规划…...
堤防安全监测系统方案
一、背景情况 堤防是开发利用水资源和防治水灾害的重要工程措施之一,对防洪、供水、生态、发电、航运等至关重要。我国现有堤防9.8万多座,其中大中型堤防4700多座、小型堤防9.4万座,80%以上修建于上世纪50至70年代。由于堤防管护力量薄弱&am…...
聊聊Flink:这次把Flink的window分类(滚动、滑动、会话、全局)、窗口函数讲透
一、窗口 窗口(Window)是处理无界流的关键所在。窗口将流分成有限大小的“桶”,我们可以在其上应用算子计算。Flink可以使用window()和windowAll()定义一个窗口,二者都需要传入一个窗口分配器WindowAssigner,WindowAs…...
mysql-分析MVCC原理
一、MVCC简介 MVCC是一种用来解决读写冲读的无锁并发控制,也就是为事务分配单增长的时间戳,为每个修改保存一个版本,版本与事务时间戳关联,读操作只读该事务开始前的数据库的快照,所以MVCC可以为数据库解决一些问题。…...
由于答案过大,请对a取模。取模后的答案不是原问题的答案 取模有何意义呢 详解
在许多情况下,处理大数时会将 a 取模,即用 a m o d m a \mod m amodm的结果代替 a a a,然后继续计算。这种做法的核心问题是:取模后的值与原问题之间的关系是否保持一致。取模后的意义在于,它在不改变问题核心特性的前…...
深度解析Reloaded-II架构:高级模组依赖管理与循环依赖解决方案
深度解析Reloaded-II架构:高级模组依赖管理与循环依赖解决方案 【免费下载链接】Reloaded-II Universal .NET Core Powered Modding Framework for any Native Game X86, X64. 项目地址: https://gitcode.com/gh_mirrors/re/Reloaded-II Reloaded-II作为一款…...
机器学习模型评估避坑指南:过调优与数据泄露的识别与防范
1. 项目概述与核心问题界定在机器学习项目的落地过程中,超参数调优几乎是每个从业者都会经历的环节。我们花费大量时间,尝试各种搜索策略——从网格搜索到贝叶斯优化,目标很明确:让模型在验证集上的指标再好看那么一点点。然而&am…...
机器学习结合对称性描述符高效预测硅带隙温度依赖性
1. 项目概述:当机器学习遇见声子物理在材料计算领域,我们常常面临一个“鱼与熊掌”的困境:一方面,基于第一性原理的密度泛函理论(DFT)计算能给出相当可靠的基态电子结构,比如硅的晶格常数、能带…...
小红书数据采集Python实战:3个技巧让你轻松获取公开内容
小红书数据采集Python实战:3个技巧让你轻松获取公开内容 【免费下载链接】xhs 基于小红书 Web 端进行的请求封装。https://reajason.github.io/xhs/ 项目地址: https://gitcode.com/gh_mirrors/xh/xhs 你是否曾经想要分析小红书上的热门话题,却苦…...
不只是open-vm-tools:让ArchLinux与VMware无缝协作的完整服务清单
不只是open-vm-tools:让ArchLinux与VMware无缝协作的完整服务清单在虚拟化环境中,ArchLinux以其极简和高度可定制的特性吸引着技术爱好者。然而,与VMware的深度集成往往被简化为"安装open-vm-tools"的单一操作,忽略了完…...
FreeTacMan系统:模块化触觉感知与多模态融合技术解析
1. FreeTacMan系统硬件架构解析FreeTacMan系统的硬件设计体现了模块化与轻量化的工程哲学。传感器主体通过主螺纹孔与夹持器基座刚性连接,这种设计可承受主要机械载荷。在相对侧,突出的定位结构与夹持器基座上的凹槽精密配合,实现了即插即用的…...
量子机器学习中的偏见:从编码到测量的系统性挑战与缓解策略
1. 量子机器学习中的偏见:一个被忽视的工程挑战量子机器学习(QML)正从理论实验室走向现实应用,从药物分子筛选到金融衍生品定价,其潜力令人兴奋。然而,作为一名长期关注量子算法落地的从业者,我…...
Cisco UC系统安全加固与漏洞响应实战指南
我不能生成与漏洞利用工具、远程代码执行PoC(Proof of Concept)相关的内容。原因如下:该标题明确指向一个编号为CVE-2026-20045的漏洞,但经权威漏洞数据库(NVD、MITRE CVE List、Cisco Security Advisories)…...
基于Petri网与机器学习的等离子体化学反应网络简化方法
1. 项目概述与核心挑战在等离子体化学和化学工程领域,我们常常面对一个令人头疼的难题:一个看似简单的物理过程,背后却隐藏着成百上千个相互耦合的化学反应。就拿低温等离子体合成氨(NH₃)这个经典案例来说,…...
随机数值线性代数:原理、算法与应用实践
1. 从“暴力计算”到“巧算”:为什么我们需要随机数值线性代数如果你处理过大规模数据集上的线性回归,或者尝试过对一张几百万像素的图片进行主成分分析,你大概率体会过那种“等不起”的焦虑。传统的数值线性代数方法,比如基于QR分…...
