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

在这里插入图片描述

简介:本文深入探讨图像梯度相关知识,详细介绍图像梯度是像素灰度值在不同方向的变化速度,并以 “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()

a
你观察图片可以发现,他只找到了一条的边,可是这个方向的边应该有两条。原因是因为白色是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(),有两个区别就是

  1. scharr没有ksize这个参数。
  2. 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图像处理(十一)—图像梯度
一文讲解图像梯度

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

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

相关文章

解决IDEA报包不存在,但实际存在的问题

前言 最近在把一个亿老项目交割给同事,同事在导入项目运行时遇到IDEA报包不存在,但实际存在的问题,最终通过以下方式解决 现象 在IDEA里启动运行项目,报某个类有问题,引入的包不存在。 点击这个引入的包,可…

C++(进阶) 第1章 继承

C(进阶) 第1章 继承 文章目录 前言一、继承1.什么是继承2.继承的使用 二、继承方式1.private成员变量的(3种继承方式)继承2. private继承方式3.继承基类成员访问⽅式的变化 三、基类和派生类间的转换1.切片 四、 继承中的作⽤域1.隐藏规则&am…

resnet50,clip,Faiss+Flask简易图文搜索服务

一、实现 文件夹目录结构&#xff1a; templates -----upload.html faiss_app.py 前端代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widt…

SFP+光模块介绍

SFP光模块介绍 1 SFP光模块简介(Small Form -Factor Pluggable)2 光模块管脚定义 1 SFP光模块简介(Small Form -Factor Pluggable) 光模块&#xff08;Optical Module&#xff09;由光电子器件、功能电路和光接口等组成&#xff0c;光电子器件包括激光发射器(Laser Transmitte…

Redis——Raft算法

Raft使用较为广泛的强一致性、去中心化、高可用的分布式协议&#xff0c;即使在网络、节点故障等情况下&#xff0c;多个节点依然能达到一致性。 其中redis、etcd等都用到了这种算法 在Redis集群中&#xff0c;采取的主从复制结构&#xff0c;当主节点宕机后&#xff0c;哨兵会…

【网络系统管理】2023年全国职业院校技能大赛:组策略--10套题组合--3

11、阻止Microsoft账户登录 (1)计算机配置\策略\Windows设置\安全设置\本地策略\安全选项 12、允许更改系统时间 (1)计算机配置\策略\Windows设置\安全设置\本地策略\用户权限分配 13、可以登录本机的用户 (1)计算机配置\策略\Windows设置\安全设置\本地策略\用户权限…

Glide源码学习

前言 开始 基本使用非常简单&#xff0c;链式调用把context对象传入&#xff0c;设置要加载的URL&#xff0c;设置要填充的ImageView控件&#xff0c;方法很简洁&#xff0c;每次都是传入的最核心的参数&#xff0c;底层加载的缓存逻辑&#xff0c;加载的引擎&#xff0c;加载…

基于RFSOC实现LFMCW雷达测距测速

雷达原理可以参考以下文章 https://zhuanlan.zhihu.com/p/508764579 一般情况下&#xff0c;雷达发射信号的模型可采用线性调频连续波&#xff08;LFMCW&#xff09; &#xff0c;发射波形的信号形式为调频连续锯齿波。线性调频的含义即调制信号频率随时间线性变化&#xff0c…

VELO SkyOW+坐垫,一起Cityride温暖你的上海之旅

随着冬季的到来&#xff0c;上海的街头巷尾弥漫着一种独特的浪漫气息&#xff0c;当金黄的落叶从空中飘落&#xff0c;铺满路边&#xff0c;只是路过就仿佛骑进了一幅世界名画。无论是沿着外滩漫游&#xff0c;还是穿行在浦东的高楼间&#xff0c;骑行的方式总能让你充分体验到…

基于lora的llama2二次预训练

基于lora的llama2二次预训练 一、为什么需要对llama2做基于lora的二次预训练? 加入中文训练语料进行llama2的二次预训练&#xff0c;这样模型就可以增加支持中文输出的能力。 二、基于lora的llama2二次预训练的目标是什么&#xff1f; 在保持预训练模型权重不变的情况下&a…

探索 Python 任务自动化的新境界:Invoke 库揭秘

文章目录 探索 Python 任务自动化的新境界&#xff1a;Invoke 库揭秘背景&#xff1a;为何选择 Invoke&#xff1f;什么是 Invoke&#xff1f;如何安装 Invoke&#xff1f;5个简单的库函数使用方法1. 定义任务2. 带参数的任务3. 运行 Shell 命令4. 任务参数化5. 列出任务 场景应…

利用Prompt工程为LLM提升推理能力

利用Prompt工程为LLM提升推理能力 基于策略的推理详解ReAct: 推理与行动思维链&#xff1a;逐步解决问题反思&#xff1a;深入分析和自我审查与代理架构的集成实际应用代码附录 众所周知&#xff0c;一个精心设计的Prompt能够显著增强大型语言模型&#xff08;LLMs&#xff09;…

C#开发合集

用C#轻松搞定m3u8视频下载与合并 嘿&#xff0c;程序员们&#xff01;今天咱们来聊聊如何用C#写个小程序&#xff0c;轻松下载和合并m3u8视频文件。没错&#xff0c;就是那种分段的流媒体视频。准备好了吗&#xff1f;让我们开始吧&#xff01; 准备工作 在动手之前&#xf…

java框架Netty网络编程——问鼎篇

Netty进阶 粘包现象 案例 服务端代码 public static void main(String[] args) {NioEventLoopGroup bossGroupnew NioEventLoopGroup(1);NioEventLoopGroup workerGroupnew NioEventLoopGroup(2);try {ServerBootstrap serverBootstrap new ServerBootstrap();serverBootstr…

堤防安全监测系统方案

一、背景情况 堤防是开发利用水资源和防治水灾害的重要工程措施之一&#xff0c;对防洪、供水、生态、发电、航运等至关重要。我国现有堤防9.8万多座&#xff0c;其中大中型堤防4700多座、小型堤防9.4万座&#xff0c;80%以上修建于上世纪50至70年代。由于堤防管护力量薄弱&am…

模型减肥秘籍:模型压缩技术 知识蒸馏

教程链接&#xff1a;模型减肥秘籍&#xff1a;模型压缩技术-课程详情 | Datawhale 知识蒸馏&#xff1a;让AI模型更轻更快 在人工智能快速发展的今天&#xff0c;我们经常需要在资源受限的设备&#xff08;如手机、IoT设备&#xff09;上运行AI模型。但这些设备的计算能力和…

golang实现TCP服务器与客户端的断线自动重连功能

1.服务端 2.客户端 生成服务端口程序: 生成客户端程序: 测试断线重连: 初始连接成功

React表单联动

Ant Design 1、dependencies Form.Item 可以通过 dependencies 属性&#xff0c;设置关联字段。当关联字段的值发生变化时&#xff0c;会触发校验与更新。 一种常见的场景&#xff1a;注册用户表单的“密码”与“确认密码”字段。“确认密码”校验依赖于“密码”字段&#x…

springboot实战(16)(Validation参数校验冲突问题、分组校验、默认分组)

目录 一、注解NotNull与NotEmpty区别。 二、Validation提供的分组校验。&#xff08;参数校验冲突问题&#xff09; &#xff08;1&#xff09;基本介绍。 &#xff08;2&#xff09;实际案例。 &#xff08;3&#xff09;大模型提问提供的方法。 1、定义分组接口。 2、在字段上…

学Linux的第九天--磁盘管理

目录 一、磁盘简介 &#xff08;一&#xff09;、认知磁盘 &#xff08;1&#xff09;结构 &#xff08;2&#xff09;物理设备的命名规则 &#xff08;二&#xff09;、磁盘分区方式 MBR分区 MBR分区类型 扩展 GPT格式 lsblk命令 使用fdisk管理分区 使用gdisk管理分…