若楠带你初识OpenCV(4) -- 图像边缘检测

news2024/11/23 22:38:25

文章目录

  • OpenCV
  • 图像边缘检测
    • sobel 算子
      • 1. x方向上的边缘
      • 2. 保存负值
      • 3. 取绝对值
      • 4. y方向上的边缘
      • 5. 加权运算
      • 不要双方向同时卷积
      • 读取猪猪侠查看效果
    • Scharr 算子
    • Laplacian 算子
  • canny边缘检测
    • 优点
    • 理论步骤四部分
      • 1. 图像降噪
      • 2. 梯度计算
      • 3. 非极大值抑制
      • 4. 双阈值边界跟踪
    • 示例应用
  • 总结

OpenCV

OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习库,它主要用于实时图像处理和计算机视觉任务。

本篇所用图片数据:

链接:图片数据
https://pan.baidu.com/s/1-C6sxtw-S3vL1I5SwaStlQ?pwd=dzvx
提取码:dzvx

图像边缘检测

边缘检测:是图形图像处理、计算机视觉和机器视觉中的一个基本工具,通常用于特征提取和特征检测,旨在检测一张数字图像中有明显变化的边缘或者不连续的区域。

边缘检测的方法有:sobel算子、Scharr算子、Laplacian算子以及Canny边缘检测。

sobel 算子

Sobel 算子是一种离散的微分算子,该算子结合了高斯平滑和微分求导运算。该算子利用局部差分寻找边缘,计算所得的是一个梯度的近似值。

Sobel算子包含2组3×3的矩阵,分别为横向和纵向模板,将之与图像作平面卷积,即可分别得出横向及纵向的亮度差分近似值。

在这里插入图片描述

目标步骤:得到x方向的边缘,在得到y方向上的边缘,将二者整合,即可得到一个完整的边缘。

1. x方向上的边缘

yuan = cv2.imread('yuan.png')
cv2.imshow('yuan',yuan)
cv2.waitKey(0)

# x方向上的边缘
# -1:该位置参数表示图像深度,-1表示与传入图片相同;dx,dy表示卷积方向
yuan_x = cv2.Sobel(yuan,-1,dx=1,dy=0)
cv2.imshow('yuan_x',yuan_x)
cv2.waitKey(0)

在这里插入图片描述

我们发现图片右边的边缘没有显示出来,那是因为在卷积计算时,右边计算的值为负值,但是范围为【0~255】,所以没有得到负值,那我们要如何将复制保存下来呢?

2. 保存负值

默认参数uint8改为float64,可保存负数
修改过后:x方向上的边缘,包括负数信息(右边),已经保存了,但是显示不出来,因为范围是(0~255
# x方向上的边缘,包括负数信息(右边),已经保存了,但是显示不出来,因为范围是(0~255)
yuan_x_64 = cv2.Sobel(yuan,cv2.CV_64F,dx=1,dy=0) # 默认uint8改为float64,可保存负数
cv2.imshow('yuan_x_64',yuan_x_64)
cv2.waitKey(0)

在这里插入图片描述

由于负值无法显示,所以图片依然只有一半,那我们该怎么将另一半显示出来呢?简单理解,负值显示不出来,那就将它转化为正值呗~,将其绝对值。

3. 取绝对值

cv2.convertScaleAbs()方法
# 若想将负数值部分显示出来,可将它们取绝对值
yuan_x_full = cv2.convertScaleAbs(yuan_x_64) # 转化为绝对值,负数转化为正数
cv2.imshow('yuan_x_full',yuan_x_full)
cv2.waitKey(0)

在这里插入图片描述

这样我们就可以看见一个完整x方向的边缘咯。

当然,这只是单一x方向上的边缘,我们还需要得到y方向的边缘。

4. y方向上的边缘

重复获得x方向边缘的步骤:

# y方向上边缘
yuan_y = cv2.Sobel(yuan,-1,dx=0,dy=1)
cv2.imshow('yuan_y',yuan_y)
cv2.waitKey(0)

yuan_y_64 = cv2.Sobel(yuan,cv2.CV_64F,dx=0,dy=1)
yuan_y_full = cv2.convertScaleAbs(yuan_y_64)
cv2.imshow('yuan_y_full',yuan_y_full)
cv2.waitKey(0)

在这里插入图片描述

5. 加权运算

图像加权运算,将x,y两个方向上的边缘组合在一起:

yuan_xy_full = cv2.addWeighted(yuan_x_full,1,yuan_y_full,1,0)
cv2.imshow('yuan_xy_full',yuan_xy_full)
cv2.waitKey(0)

在这里插入图片描述

这样我们就完整得到了圆的边缘,那么为什么我们不直接对x和y方向同时卷积呐?

不要双方向同时卷积

  • 结果混淆:如果尝试同时对图像进行水平和垂直两个方向的卷积,并将结果直接相加或合并,可能会导致边缘检测的结果变得混淆不清。因为每个像素点在不同方向上的边缘强度可能不同,直接合并可能无法准确反映真实的边缘信息。
  • 计算复杂度增加:虽然现代计算机的计算能力强大,但无意义的双方向同时卷积会增加不必要的计算量,降低处理速度。
  • 边缘定位精度:Sobel算子本身在边缘定位上可能存在一定的模糊性,双方向同时卷积可能会进一步加剧这一问题,使得边缘检测结果不够精确。

尝试双方向一起卷积:

# 同时使用x,y方向边缘(不建议使用)
yuan_xy = cv2.Sobel(yuan,-1,dx=1,dy=1)
cv2.imshow('yuan_xy',yuan_xy)
cv2.waitKey(0)

在这里插入图片描述

读取猪猪侠查看效果

"""---------sobel算子---------"""
a = cv2.imread('GGbond.jpg',cv2.IMREAD_GRAYSCALE)
gg = cv2.resize(a,dsize=None,fx=0.5,fy=0.5)
gg_x_64 = cv2.Sobel(gg,cv2.CV_64F,dx=1,dy=0)
gg_x_full = cv2.convertScaleAbs(gg_x_64)
gg_y_64 = cv2.Sobel(gg,cv2.CV_64F,dx=0,dy=1)
gg_y_full = cv2.convertScaleAbs(gg_y_64)
gg_xy_Sobel_full = cv2.addWeighted(gg_x_full,1,gg_y_full,1,0)
cv2.imshow('gg_xy_Sobel_full',gg_xy_Sobel_full)
cv2.waitKey(0)

在这里插入图片描述

Scharr 算子

Scharr 算子是 Soble 算子在 ksize=3 时的优化,与 Soble 的速度相同,且精度更高。Scharr 算子与 Sobel 算子的不同点是在平滑部分,其中心元素占的权重更重,相当于使用较小标准差的高斯函数,也就是更瘦高的模板。

所以Scharr 算子在操作方面与Sobel算子相同:

"""--------Scharr算子-------"""
a = cv2.imread('GGbond.jpg',cv2.IMREAD_GRAYSCALE)
gg = cv2.resize(a,dsize=None,fx=0.5,fy=0.5)
# x方向
gg_x_64 = cv2.Scharr(gg,cv2.CV_64F,dx=1,dy=0)
gg_x_full = cv2.convertScaleAbs(gg_x_64)
# y方向
gg_y_64 = cv2.Scharr(gg,cv2.CV_64F,dx=0,dy=1)
gg_y_full = cv2.convertScaleAbs(gg_y_64)
# 加权
gg_xy_Scharr_full = cv2.addWeighted(gg_x_full,1,gg_y_full,1,0)
cv2.imshow('gg_xy_Scharr_full',gg_xy_Scharr_full)
cv2.waitKey(0)

在这里插入图片描述

Laplacian 算子

Laplacian 算子不再以x和y的方向计算,而是以圆方向计算变化率。因此不需要Gx+Gy。故而,不需要分两个方向分别取边缘。

"""-----Laplacian算子-----"""
a = cv2.imread('GGbond.jpg',cv2.IMREAD_GRAYSCALE)
gg = cv2.resize(a,dsize=None,fx=0.5,fy=0.5)

# 算子计算
gg_lap = cv2.Laplacian(gg,cv2.CV_64F)
# 绝对值
gg_lap_full = cv2.convertScaleAbs(gg_lap)

cv2.imshow('gg_lap_full',gg_lap_full)
cv2.waitKey(0)

在这里插入图片描述

canny边缘检测

优点

Canny边缘检测的优点:

  • 低错误率。因为一般的边缘检测算子可能存在检测到伪边缘的情况,因此Canny算法检测到的边缘尽可能地是真实的边缘。
  • 较好地定位边缘点。由检测器标记的边缘点与真实边缘点中心尽可能地接近。
  • 单一的边缘响应。图像中的边缘只标记出一次。

理论步骤四部分

canny边缘检测分为四个部分:1、图像降噪,2、梯度计算,3、非极大值抑制,4、双阈值边界跟踪

1. 图像降噪

图像去噪是进行边缘检测的第一步,通过去噪可以去除图像中的一些噪点,从而使边缘检测时免受噪点干扰。

降噪方法:高斯滤波

2. 梯度计算

要进行边缘检测,就需要得到图像梯度信息,根据图像的梯度幅值和梯度方向来确定边缘,一般均采用sobel算子对图像进行梯度幅值与梯度方向计算。

3. 非极大值抑制

一阶微分在灰度值斜坡过渡时不为零且存在较粗的边缘,较粗的边缘会增大边缘检测的误差,因此需要细化边缘,一种较为常用的方法是非极大值抑制。

非极大值抑制:即在梯度图像中寻找梯度方向上的最大值作为边缘,不是梯度方向上的最大值则抑制为0。因为梯度方向是灰度变化最大的方向。比较梯度图像中每一点的灰度值与梯度方向上至少两个梯度图像像素点灰度值的大小,根据上述大小关系来确定是否保留该点的灰度值。

在这里插入图片描述

4. 双阈值边界跟踪

双阈值处理就是根据实际情况需要设置一个灰度高阈值和一个灰度低阈值对NMS后的图像进行过滤,使得得到的边缘尽可能是真实的边缘。

在这里插入图片描述

示例应用

虽然canny边缘检测的理论看起来比较复杂,但是在应用时却很简单,因为上述步骤的操作已经都写在了cv2.Canny()方法中,只需要调用该函数即可应用:

"""-----canny边缘检测-----"""
a = cv2.imread('GGbond.jpg',cv2.IMREAD_GRAYSCALE)
gg = cv2.resize(a,(400,400))
gg_canny = cv2.Canny(gg,100,150)#设置阈值 低,高
cv2.imshow('gg_canny',gg_canny)
cv2.waitKey(0)

在这里插入图片描述

我们可以看到,canny边缘检测的方法对图像处理效果很好,边缘清晰,线条简单。

总结

本篇介绍了图像的边缘检测方法:

  1. sobel 算子:分为x和y两个方向计算
  2. Scharr 算子:是sobel 算子在 ksize=3 时的优化,也是分为x和y两个方向计算
  3. Laplacian 算子:不再以x和y的方向计算,而是以圆方向计算变化率
  4. canny边缘检测:高效、准确,寻找最优边缘

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

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

相关文章

【QT | 开发环境搭建】windows系统(Win10)安装 QT 5.12.12 开发环境

😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C、数据结构、音视频🍭 ⏰发布时间⏰: 本文未经允许…

WebStorm用Debug模式调试Vue项目

问题说明 开发前端代码时,一直很苦恼调试前端代码的麻烦。 简单的内容可以通过console.log()在控制台打印变量值,来验证预期结果。 涉及到稍复杂的逻辑,就需要在代码中侵入增加debugger,或者在浏览器中找到js文件,再手…

Linux 之 mysql-5.7.44 下载/安装(离线)

下载 官网 MySQL :: Download MySQL Community Server (Archived Versions) 安装 1.解压并放到指定目录(/home/mysql) tar -zxvf mysql-5.7.44-el7-x86_64.tar.gz 移动到指定安装位置(我的:/home 下) mv mysql-5.…

实操在聆思CSK6大模型开发板的英文评测SDK中自定义添加单词、短语、句子资源

引言 英文评测示例通过对用户语音输入的英文单词进行精准识别,提供 单词、短语、句子 三种类型,用户在选择好类型后,可根据屏幕上的提示进行语音输入,评测算法将对输入的英文语音进行精准识别,并对单词的发音、错读、漏…

Codeforces Round 970 (Div. 3)(ABCDEF)

Codeforces Round 970 (Div. 3) A:Sakurakos Exams 签到 题意:给定1,2的数量,判断是否能用加减符号使得这些1,2计算出0 void solve() {cin>>n>>m;if(n%2)cout<<"NO\n";else{if(m%20||n)cout<<"YES\n";else cout<<"…

作为前端,感受一下MemFire Cloud带来的魅力

作为一名前端开发者&#xff0c;你是否曾为后台开发的繁琐和复杂而头疼&#xff1f;是否想过只需要专注于前端界面&#xff0c;而所有的后端工作都能一键搞定&#xff1f;如果你有这些想法&#xff0c;那么MemFire Cloud 无疑会成为你开发路上的新神器。 什么是MemFire Cloud…

SpringBoot学习(8)RabbitMQ详解

RabbitMQ 即一个消息队列&#xff0c;主要是用来实现应用程序的异步和解耦&#xff0c;同时也能起到消息缓冲&#xff0c;消息分发的作用。 消息中间件最主要的作用是解耦&#xff0c;中间件最标准的用法是生产者生产消息传送到队列&#xff0c;消费者从队列中拿取消息并处理&…

搞定JavaScript异步原理,深入学习Promise

JS异步及Promise基础 一、从浏览器运行机制说起 来破案啦&#xff0c;常说的“多线程的浏览器、单线程的Javascript”到底是什么意思&#xff1f;单线程的Javascript是否真的需要抽身去计时、去发http请求&#xff1f;第一部分我们重新从浏览器运行机制开始认识一下JavaScript…

828华为云征文 | Flexus X实例与华为云EulerOS的Tomcat安装指南

文章目录 前言安全组设置操作步骤软件安装配置软件验证Tomcat安装是否成功 总结 前言 Tomcat是一个由Apache软件基金会开发并维护的免费、开源的Web应用服务器。它主要用于处理Java Servlet、JavaServer Pages&#xff08;JSP&#xff09;和JavaServer Pages Standard Tag Lib…

新增一个数组传递给后端

实现的效果&#xff1a; 页面 <div style"margin-bottom: 10px" v-if"totalPrice"><p style"font-weight: bolder;margin-bottom: 10px">支付计划<el-button type"text" size"small" click"addPayInf…

53 mysql pid 文件的创建

前言 接上一篇文章 mysql 启动过程中常见的相关报错信息 在 mysql 中文我们在 “service mysql start”, “service mysql stop” 经常会碰到 mysql.pid 相关的错误信息 比如 “The server quit without updating PID file” 我们这里来看一下 mysql 中 mysql.pid 文件的…

软件工程知识点总结(2):需求分析(一)——用例建模

1 软件项目开发流程&#xff1a; 需求分析→概要设计→详细设计→编码实施→测试→产品提 交→维护 2 系统必须做什么&#xff1f; 获取用户需求&#xff0c;从用户角度考虑&#xff0c;用户需要系统必须完成哪些工作&#xff0c;也就是对目 标系统提出完整、准确、清晰、具体…

算法day22|组合总和 (含剪枝)、40.组合总和II、131.分割回文串

算法day22|组合总和 &#xff08;含剪枝&#xff09;、40.组合总和II、131.分割回文串 39. 组合总和 &#xff08;含剪枝&#xff09;40.组合总和II131.分割回文串 39. 组合总和 &#xff08;含剪枝&#xff09; 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 ta…

使用Node-API实现跨语言交互开发流程

一、前言 使用Node-API实现跨语言交互&#xff0c;首先需要按照Node-API的机制实现模块的注册和加载等相关动作。 ArkTS/JS侧&#xff1a;实现C方法的调用。代码比较简单&#xff0c;import一个对应的so库后&#xff0c;即可调用C方法。 Native侧&#xff1a;.cpp文件&#xf…

【C语言】十六进制、二进制、字节、位、指针、数组

【C语言】十六进制、二进制、字节、位 文章目录 [TOC](文章目录) 前言一、十六进制、二进制、字节、位二、变量、指针、指针变量三、数组与指针四、指针自加运算五、二维数组与指针六、指向指针的指针七、指针变量作为函数形参八、函数指针九、函数指针数组十、参考文献总结 前…

JVM面试(六)垃圾收集器

目录 概述STW收集器的并发和并行 Serial收集器ParNew收集器Parallel Scavenge收集器Serial Old收集器Parallel Old收集器CMS收集器Garbage First&#xff08;G1&#xff09;收集器 概述 上一章我们分析了垃圾收集算法&#xff0c;那这一章我们来认识一下这些垃圾收集器是如何运…

某云彩SRM2.0任意文件下载漏洞

文章目录 免责申明搜索语法漏洞描述漏洞复现修复建议 免责申明 本文章仅供学习与交流&#xff0c;请勿用于非法用途&#xff0c;均由使用者本人负责&#xff0c;文章作者不为此承担任何责任 搜索语法 fofa icon_hash"1665918155"漏洞描述 某云采 SRM2.0是一款先…

制作自己的游戏:打砖块

文章目录 &#x1f680; 前言&#x1f680; 前期准备&#x1f680; 玩法设计&#x1f680; 游戏场景&#x1f353; 什么是游戏场景&#x1f353; 绘制左上角积分&#x1f353; 绘制右上角生命值&#x1f353; 绘制砖块&#x1f353; 绘制小球&#x1f353; 绘制挡板&#x1f35…

场景是人工智能第四要素,是垂直领域人工智能的第一要素。

"场景是人工智能的第四要素&#xff0c;与数据、算力、算法同等重要。"拿着技术找场景&#xff0c;还是拿着场景找技术&#xff1f;这个锤子和钉子的问题&#xff0c;一直困扰着各家AI大厂。从近5年的实践来看&#xff0c;拿着场景找技术是更为稳健的&#xff0c;否则…

文章解读与仿真程序复现思路——电力自动化设备EI\CSCD\北大核心《面向电网调峰的聚合温控负荷多目标优化控制方法 》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…