【OpenCV实现图像梯度,Canny边缘检测】

文章目录

    • 概要
    • 图像梯度
    • Canny边缘检测
    • 小结

概要

OpenCV中,可以使用各种函数实现图像梯度和Canny边缘检测,这些操作对于图像处理和分析非常重要。

图像梯度通常用于寻找图像中的边缘和轮廓。在OpenCV中,可以使用cv2.Sobel()函数计算图像的梯度,该函数可以计算图像在水平和垂直方向上的梯度。梯度的方向和大小可以帮助理解图像中的边缘信息。

Canny边缘检测是一种经典的边缘检测算法,它通过多个步骤来检测图像中的边缘。首先,Canny算法使用Sobel算子计算图像的梯度。然后,它通过非极大值抑制(Non-Maximum Suppression)来细化边缘。接着,Canny算法使用双阈值(Double Thresholding)来检测强边缘和弱边缘,并通过连接强边缘来得到最终的边缘图像。Canny边缘检测在图像处理中被广泛应用,因为它能够准确地检测出图像中的边缘。

在OpenCV中,可以使用cv2.Sobel()函数计算图像的梯度,而Canny边缘检测则可以通过cv2.Canny()函数实现。通过这些函数,可以方便地在OpenCV中实现图像梯度和Canny边缘检测,进而进行各种图像分析和处理任务。

图像梯度

寻找图像梯度,边缘等等。
函数:cv.Sobel(), cv.Scharr(), cvLaplacian() 等等。

Sobel和Scharr导数:
Sobel算子是一种结合了高斯平滑和微分操作的滤波器,因此它对图像中的噪声具有较好的抵抗能力。使用Sobel算子时,可以指定所需导数的方向,通过参数yorder和xorder来确定是垂直方向还是水平方向的导数。此外,还可以通过参数ksize指定核(kernel)的大小。当ksize设为-1时,OpenCV会使用3×3的Scharr滤波器,其结果通常比3×3的Sobel滤波器更为精确。

拉普拉斯导数
它计算了由关系式给出的图像的拉普拉斯算子,其中关系式为
在这里插入图片描述
其中每一个导数都是用 Sobel 导数找到的。如果 ksize = -1,滤波器会使用下面这个内核。

在这里插入图片描述

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt# 读取图像
img = cv.imread('dave.jpg', 0)# 计算拉普拉斯边缘
laplacian = cv.Laplacian(img, cv.CV_64F)# 计算Sobel边缘(x和y方向)
sobelx = cv.Sobel(img, cv.CV_64F, 1, 0, ksize=5)
sobely = cv.Sobel(img, cv.CV_64F, 0, 1, ksize=5)# 绘制原始图像
plt.subplot(2, 2, 1), plt.imshow(img, cmap='gray')
plt.title('Original'), plt.xticks([]), plt.yticks([])# 绘制拉普拉斯边缘图像
plt.subplot(2, 2, 2), plt.imshow(laplacian, cmap='gray')
plt.title('Laplacian'), plt.xticks([]), plt.yticks([])# 绘制Sobel X边缘图像
plt.subplot(2, 2, 3), plt.imshow(sobelx, cmap='gray')
plt.title('Sobel X'), plt.xticks([]), plt.yticks([])# 绘制Sobel Y边缘图像
plt.subplot(2, 2, 4), plt.imshow(sobely, cmap='gray')
plt.title('Sobel Y'), plt.xticks([]), plt.yticks([])# 显示图像
plt.show()

在这里插入图片描述
在我们的最后一个例子中,我们使用了Sobel滤波器来检测图像中的边缘。然而,当我们将输出数据类型转换为cv.CV_8U或者np.uint8时,存在一个小问题。在图像中,从黑色到白色的过渡被视为正斜率(它具有正值),而从白色到黑色的过渡被视为负斜率(它具有负值)。因此,当我们将数据类型转换为np.uint8时,所有负斜率都被截断为0,也就是说,我们会错过所有负斜率对应的边缘。

如果我们希望找到所有的边缘,更好的方法是将输出的数据类型保持在一个更高的精度范围内,例如cv.CV_16S、cv.CV_64F等,然后取其绝对值,最后再转换回cv.CV_8U类型。下面的代码演示了这个过程,特别是在处理水平Sobel滤波器时,以及结果的差异。

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt# 读取灰度图像
img = cv.imread('img.png', 0)# 使用Sobel滤波器,输出数据类型为cv.CV_8U
sobelx8u = cv.Sobel(img, cv.CV_8U, 1, 0, ksize=5)# 使用Sobel滤波器,输出数据类型为cv.CV_64F,然后取绝对值并转换为cv.CV_8U
sobelx64f = cv.Sobel(img, cv.CV_64F, 1, 0, ksize=5)
abs_sobel64f = np.absolute(sobelx64f)
sobel_8u = np.uint8(abs_sobel64f)# 显示原始图像、Sobel输出(cv.CV_8U)和Sobel绝对值(cv.CV_64F)
plt.subplot(1, 3, 1), plt.imshow(img, cmap='gray')
plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(1, 3, 2), plt.imshow(sobelx8u, cmap='gray')
plt.title('Sobel CV_8U'), plt.xticks([]), plt.yticks([])
plt.subplot(1, 3, 3), plt.imshow(sobel_8u, cmap='gray')
plt.title('Sobel abs(CV_64F)'), plt.xticks([]), plt.yticks([])# 显示图像
plt.show()

在这里插入图片描述

Canny边缘检测

Canny边缘检测的概念
OpenCV函数:cv.Canny()

Canny边缘检测是一种广泛应用的边缘检测算法,由John F. Canny开发而成。该算法包含多个阶段,下面我们将详细介绍每个阶段的过程:

噪声减少:
由于边缘检测对图像中的噪声非常敏感,第一步是通过一个5X5的高斯滤波器对图像进行平滑处理,以去除噪声。寻找图像中的变化(梯度)强度:
接下来,使用Sobel核在水平和垂直方向上对平滑后的图像进行滤波,得到水平方向($G_x$)和垂直方向($G_y$)的一阶导数。通过这两个导数,我们可以计算每个像素点的边缘梯度幅值和方向。梯度方向始终与边缘垂直,通常近似为水平、垂直和两个对角线方向中的一个。

在这里插入图片描述

非极大值抑制:
在得到梯度大小和方向之后,在每个像素点上进行全图扫描。对于每个像素,检查其梯度值是否在相邻像素中是最大的。如果是,保留该值,否则将其置为0。这一步骤产生了一个"薄边"的二值图像。

在这里插入图片描述
滞后阈值:
在此阶段,我们需要确定哪些边缘是真实的,哪些是噪声或者假的。为此,我们使用两个阈值,minVal(最小值)和maxVal(最大值)。所有强度大于maxVal的边缘被视为真正的边缘,低于minVal的被丢弃。介于两者之间的边缘会基于连通性来判断是否为边缘。如果它们与确定的边缘相连,则保留,否则被抛弃。这一步骤也基于边缘是长线的假设来去除小的像素噪声。
在这里插入图片描述
边缘 A 因为在 maxVal 上面,所以是肯定的边缘。尽管边缘 C 的位置在 maxVal 下面,但是因为它和边缘 A 相连接,所以我们认为它也是个有效边缘,如此得到了一条完整的曲线。但是对于边缘 B 来说,哪怕它在 minVal 上面,和边缘 C 处在同一个区域上,可是它并不和任何一条有效边缘连接,所以会被丢弃。所以,为了得到正确的结果,我们需要确定好 minVal 和 maxVal 的值。

最终,经过这些步骤,我们就能得到一条完整的边缘在图像中。

OpenCV中的Canny边缘检测

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt# 读取灰度图像
img = cv.imread('img.png', 0)# 使用Canny边缘检测算法,阈值设置为100和200
edges = cv.Canny(img, 100, 200)# 显示原始图像和Canny边缘检测结果
plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])plt.subplot(122), plt.imshow(edges, cmap='gray')
plt.title('Edge Image'), plt.xticks([]), plt.yticks([])plt.show()

在这里插入图片描述

小结

图像梯度:

OpenCV提供了多种方法来计算图像的梯度,包括Sobel、Scharr和拉普拉斯滤波器。
Sobel算子是一种联合高斯平滑和微分操作的滤波器,可以计算图像在水平和垂直方向上的梯度。
使用Sobel算子时,你可以指定所需导数的方向(水平或垂直)以及核的大小。
拉普拉斯滤波器用于计算图像的拉普拉斯算子,通过将图像的二阶导数与Sobel导数相关联来实现。

Canny边缘检测:

Canny边缘检测是一种多阶段算法,用于检测图像中的边缘。
第一阶段是噪声减少,通常通过应用高斯滤波器来实现,以平滑图像并减少噪声。
第二阶段是计算图像的梯度,通常使用Sobel滤波器,以获得图像的水平和垂直梯度。
接下来进行非极大值抑制,以去除可能不构成边缘的像素,仅保留边缘像素。
最后一个阶段是滞后阈值,需要设置两个阈值(minVal和maxVal),以确定哪些边缘是真实的。根据这些阈值,边缘可能被分类为强边缘、弱边缘或非边缘,并进行相应的处理。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

期 货 跟 单/资 管 分 仓/镜像跟单/外 盘 分 仓的全面介绍!

期货跟单是经过科学的筛选找出合格的目标样本数据然后利用样本交易数据转化成未来实际账面利润的综合性过程。 期货跟单分为正向跟单和反向跟单,简单地说就是找出期高手正向跟随高手赚取收益或找出期货低手反向跟随赚取收益。 期货跟单软件是实现跟单过程自动化的工…

设计思想培养:装饰者模式下的RecyclerView添加头、尾

用一个设计模式培养高复用、低耦合思想 前言Android中的装饰者代码实现第一步:创建装饰器DecorateAdapter第二步:处理头部、中间内容、尾部的绑定关系第三步:装饰器的使用第四步:改进、直接封装一个View出来 总结 前言 一个高复用…

ant desigin vue3 父子 采用 emit update:xxxx传值

最近做高德地图,点击地图之后将地图上的点位从地图子组件传递给父组件,一直不大会VUE。一点一点的学吧 子组件 : map.on(click, function (e) {console.info(e.lnglat.lat, e.lnglat.lng);emit(update:lat, e.lnglat.lat);emit(update:lng, e…

第十七章 条件随机场

文章目录 导读概念符号表IOB标记概率无向图模型MRF的因子分解团与最大团有向图模型 条件随机场线性链条件随机场 特征函数对数线性模型参数化形式简化形式矩阵形式 概率计算 导读 条件随机场是给定一组输入随机变量的条件下另一组输出随机变量的条件概率分布模型,其…

SpringCloud Gateway实现请求解密和响应加密

文章目录 前言正文一、项目简介二、核心代码2.1 自定义过滤器2.2 网关配置2.3 自定义配置类2.4 加密组件接口2.5 加密组件实现,AES算法2.6 启动类,校验支持的算法配置 三、请求报文示例四、测试结果4.1 网关项目启动时4.2 发生请求时 前言 本文环境使用比…

UI动效的都可以用哪些工作来制作

随着UI设计的不断发展,UI动效越来越多地应用于现实生活中。手机,iPad、计算机、网页和其他设备被广泛使用,所以问题来了,为什么UI动态效果越来越被广泛使用?它的优点是什么?哪些软件可以设计UI动态效果&…

车载测试相比软件测试,前景会稍好一点吗?

> 如果个人是汽车、电气、工业工程相关专业的学历背景,那可以考虑从事车载测试(看上图)。> 如果不是以上专业,那就要慎重啦。 车载测试是测试行业的一个分支,最近十年一直存在,并不是这一两年才有的…

C++创建全局变量建议

建议将全局变量创建在.h/.cpp文件中,其中.h文件声明变量,.cpp文件中定义变量值。 在.h文件中定义变量,则工程多次#include该文件会出现“该文件已经被使用”。 具体示例如下: synchronize_data.h // // Created by qiaowei on…

python 数据挖掘库orange3 介绍

orange3 是一个非常适合初学者的data mining library. 它让使用者通过拖拽内置的组件来形成工作流。让你不需要写任何代码就可以体验到数据挖掘和可视化的魅力。 它的桌面如下,这里我创建了 3 个节点,分别是数据集、小提琴图,散点图 其中 …

Qt扫盲-QFutureWatcher理论总结

QFutureWatcher理论总结 一、概述二、转态 一、概述 QFutureWatcher类允许我们使用信号槽的方式去监控QFuture。 QFutureWatcher提供关于QFuture的信息和通知。使用 setFuture() 函数开始监视特定的QFuture。 future()函数通过setFuture()返回 QFuture 集合。 为了方便起见…

UE5——网络——RPC

RPC(这个是官方文档的资料) 要将一个函数声明为 RPC,您只需将 Server、Client 或 NetMulticast 关键字添加到 UFUNCTION 声明。 例如,若要将某个函数声明为一个要在服务器上调用、但需要在客户端上执行的 RPC,您可以…

【Linux】配置JDKTomcat开发环境及MySQL安装和后端项目部署

目录 一. JDK及tomcat安装 二,安装Tomcat 三,MySQL安装 四、后端部署 前言: 今天我们就来在Linux上安装JDK及tomcat,MySQL,希望你可以通过这一博客,找到你的答案!!! …

2023-macOS下安装anaconda,终端自动会出现(base)字样,如何取消

2023-macOS下安装anaconda,终端自动会出现(base)字样,如何取消 安装后,我们再打开终端,就会自动出现了(base) 就会出现这样子的,让人头大, 所以我们要解决它 具体原因是 安装了anac…

从JDBD的封装方面重新认识Mybaits

前言:SQLSession是对JDBC的封装 MyBatis 是一个 Java 持久化框架,它通过对 JDBC 的封装来简化数据库访问操作。核心的 SQLSession 对象是 MyBatis 的核心组件之一,负责管理数据库连接、执行 SQL 语句以及映射查询结果等功能。 具体来说&…

Windows11恢复组策略编辑器功能的方法

原因分析 日常工作学习中,对 Windows 计算机上的问题进行故障排除时,有些高级用户经常使用组策略编辑器轻松修复它。通过其分层结构,您可以快速调整应用于用户或计算机的设置。如果搜索结果中缺少组策略编辑器,则可能必须使用注册表编辑器作为疑难解答工具,这是一种更复杂…

nmap指纹识别要点以及又快又准之方法

nmap指纹识别要点以及又快又准之方法 一. 前言:二. nmap识别实验:一. 实验一:IP配置:空间配置:扫描结果:详细输出二. 实验二:IP配置:空间配置:扫描结果:详细输出三. 实验三:IP配置:空间配置:扫描结果:详细输出四. 实验四:IP

力扣:147. 对链表进行插入排序(Python3)

题目: 给定单个链表的头 head ,使用 插入排序 对链表进行排序,并返回 排序后链表的头 。 插入排序 算法的步骤: 插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。每次迭代中&#xff0c…

调试人脸识别项目解决方法的链接

1、failed call to cuInit: CUDA_ERROR_NO_DEVICE https://blog.csdn.net/JoyceYa/article/details/104379697/ 2、tensorflow.python.framework.errors_impl.InternalError: Blas SGEMM launch failed https://blog.csdn.net/See_Star/article/details/108762531 3、Attri…

Golang Web3钱包开发指南

简介 以太坊(Ethereum)是目前最受欢迎的区块链平台之一,它提供了智能合约功能和去中心化应用(DApps)的开发能力。在以太坊生态系统中,Web3钱包扮演着关键角色,允许用户管理账户和密钥、发送交易…

0基础学习PyFlink——时间滑动窗口(Sliding Time Windows)

在《0基础学习PyFlink——时间滚动窗口(Tumbling Time Windows)》我们介绍了不会有重复数据的时间滚动窗口。本节我们将介绍存在重复计算数据的时间滑动窗口。 关于滑动窗口,可以先看下《0基础学习PyFlink——个数滑动窗口(Sliding Count Windows&#x…