11篇--图像边缘检测

news2024/12/21 13:44:52

图像梯度

要学习图像边缘检测,要先了解图像梯度的概念,我们正是通过梯度值来区分边缘像素点的

处于边缘附近的像素点与周围像素点的差距很大(不然不会有边缘呈现),所以给边缘附近的的梯度之变化很快,通过计算梯度值,来进行边缘检测。

通常有如下两种方式处理计算得到的新值:

  • 截断处理:将小于0的值设置为0,将大于255的值设置为255。这种方法简单直接,但可能会导致图像在极端值处出现不自然的截断。
  • 归一化处理:将计算得到的值线性映射到0到255的范围内。这种方法可以保留更多的细节信息,但可能需要额外的计算。

梯度处理方式

cv2.filter2D()函数

功能:用于对图像进行卷积操作。卷积是图像处理中的一个基本操作,它通过一个称为卷积核(或滤波器)的小矩阵在图像上滑动,并对每个位置进行加权求和,从而得到新的图像。

参数:

  • src:输入图像,可以是灰度图像或彩色图像。
  • ddepth:输出图像的所需深度。对于输入图像和输出图像具有相同深度的情况,该值通常设置为 -1。否则,你可以选择一个特定的深度,如 cv2.CV_8U、cv2.CV_16U、cv2.CV_32F 等。
  • kernel:卷积核,一个二维数组或矩阵。卷积核的大小通常是奇数,如 3x3、5x5 等。卷积核中的每个元素都是一个权重,用于在卷积过程中与图像像素相乘。
  • dst:输出图像(可选)。
  • anchor:卷积核的锚点(可选)。
  • delta:一个可选的附加值,它将被加到卷积结果上。这可以用于调整结果的亮度或对比度。
  • borderType:边界填充。

进行边缘检测的方向取决于选取的卷积核kernel

kernelk1时,检测方向为垂直方向

 当kernelk2时,检测方向为水平方向

当然kernel的取值并非只有上面两种,该函数通过应用自定义的卷积核对图像进行滤波处理,可以实现各种线性滤波效果。卷积核可以看作是一种特殊的算子,但本质是函数。

注意:上面的k1,k2,正是Sobel算子(下面会讲)需要使用的卷积核,所以cv2.filter2D()函数选用上面的k1,k2作为参数kernel的取值,那么它与Sobel算子的作用效果是一样的。

那么卷积核是如何运作的呢,还跟之前一样要提前填充边缘吗?放心,不需要,计算很简单。

如下图,以垂直方向为例:

卷积核进行操作的是单信道图像,灰度图或二值图,两个极端0(黑),255(白),该卷积核进行操作目的是为进行边缘检测,所以将两个极端进行重新赋值,以便及那个边缘区分开来,下面介绍的Sobel算子,也是相同的操作,不在赘述。

 实线框部分是第一次卷积,左右两边(中间列除外)各自与对赢得系数相乘,然后进行相加

(196-247)+2*(199-241)+(35-190)= -290   结果<=0,归零,将中间一列重新赋值为零

卷积核滑动,虚线部分为第二次卷积,

(243-0)+2*(245-0)+(197-0)=930  结果>0,归255,将中间列重新赋值为255

 示例代码
import cv2
import numpy as np

# 读取一张图
img = cv2.imread("./shudu.png")

# 进行垂直梯度处理
kernel = np.array([
                [-1, 0, 1],
                [-2, 0, 2],
                [-1, 0, 1]
                   ])
img_filter = cv2.filter2D(img, -1, kernel)

# 进行水平梯度处理
kernel1 = np.array([
                [-1, -2, -1],
                [0, 0, 0],
                [1, 2, 1]
                   ])
img_filter_level = cv2.filter2D(img, -1, kernel1)

cv2.imshow('image', img)
cv2.imshow('img_filter', img_filter)
cv2.imshow('img_filter_level', img_filter_level)

cv2.waitKey(0)
效果对比

 Sobel算子

上面的两个卷积核都叫做Sobel算子,只是方向不同,它先在垂直方向计算梯度:

 cv2.Sobel()函数

功能:用于计算图像梯度(gradient)的函数

参数:

  • src: 输入图像,它应该是灰度图像。
  • ddepth: 输出图像的所需深度(数据类型)。通常,你可以使用 -1 来表示与输入图像相同的深度,或者使用如 cv2.CV_64F 等来指定特定的深度。由于梯度计算可能产生负值,因此建议使用能够包含负数的数据类型。
  • dx: x 方向上的导数阶数。如果你想要计算 x 方向上的梯度,设置这个参数为 1;如果你不关心 x 方向上的梯度,设置这个参数为 0。
  • dy: y 方向上的导数阶数。如果你想要计算 y 方向上的梯度,设置这个参数为 1;如果你不关心 y 方向上的梯度,设置这个参数为 0。通常,你不会同时设置 dx 和 dy 都为 0。
  • ksize: Sobel 核的大小。它必须是 1、3、5、7 或 9 之一。这个参数决定了用于计算梯度的滤波器的大小。大小为 1 时表示使用最小的滤波器,但通常你会使用更大的滤波器来平滑梯度计算。
  • scale: 可选参数,表示计算梯度时的缩放因子。默认值为 1,表示不进行缩放。你可以通过调整这个参数来放大或缩小梯度的结果。
  • delta: 可选参数,表示在将结果存储到目标图像之前要添加到结果中的可选增量值。默认值为 0,表示不添加增量。
  • borderType: 像素外推方法,例如 cv2.BORDER_DEFAULT、cv2.BORDER_REFLECT 等。这个参数决定了在图像边界处如何处理像素外推。
示例代码
import cv2

# 读取一张图
img = cv2.imread("./shudu.png")

# 使用sobel算子
# 水平梯度
img_sobel = cv2.Sobel(img, -1, 0, 1, ksize=3)
# 垂直梯度
img_sobel_2 = cv2.Sobel(img, -1, 1, 0, ksize=3)

cv2.imshow('image', img)
cv2.imshow('img_sobel', img_sobel)
cv2.imshow('img_sobel_2', img_sobel_2)

cv2.waitKey(0)
 效果对比

其他算子

Laplacian算子

下面为推导过程,了解即可可直接跳过,我们只关心最后的卷积核

 在此基础上考虑斜对角情况,该算子的图像卷积模板如下:

 cv2.Laplacian()函数

功能:用于计算图像的拉普拉斯算子(Laplacian)

参数:

  • src: 输入图像,它应该是灰度图像。
  • ddepth: 输出图像的所需深度。这个参数决定了输出图像的深度(数据类型)。通常,你可以使用 -1 来表示与输入图像相同的深度,或者使用 cv2.CV_64F 等来指定特定的深度。由于拉普拉斯算子可能产生负值,因此通常建议使用能够包含负数的数据类型,如 cv2.CV_64F。
  • ksize: 算子的大小。它必须是 1、3、5 或 7 之一。这个参数决定了用于计算拉普拉斯算子的滤波器的大小。大小为 1 时表示使用 4 邻域拉普拉斯算子,其他大小则使用更大的滤波器。
  • scale: 可选参数,表示计算拉普拉斯算子时的缩放因子。默认值为 1,表示不进行缩放。你可以通过调整这个参数来放大或缩小拉普拉斯算子的结果。
  • delta: 可选参数,表示在将结果存储到目标图像之前要添加到结果中的可选增量值。默认值为 0,表示不添加增量。
  • borderType: 像素外推方法,例如 cv2.BORDER_DEFAULT、cv2.BORDER_REFLECT 等。这个参数决定了在图像边界处如何处理像素外推。当 ksize 大于 1 时,这个参数才有意义。
示例代码
import cv2

# 读取一张图
img = cv2.imread("./shudu.png")

# 使用拉普拉斯算子
img_lap = cv2.Laplacian(img, -1, ksize=3)

cv2.imshow('image', img)
cv2.imshow('img_lap', img_lap)

cv2.waitKey(0)
效果对比

小结 

Sobel算子是二阶边缘检测的典型代表

Laplacian算子是二阶边缘检测的典型代表

不过 一 / 二 阶边缘检测各有优缺点,大家可自行了解。

图像边缘检测

边缘检测要用到Canny算法,Canny边缘检测方法 常被誉为 边缘检测 的最优方法。

首先,Canny算法 处理的是 图像的二值化结果,接收到二值化图像后,需要按照如下步骤进行:

  1. 高斯滤波。
  2. 计算图像的梯度和方向。
  3. 非极大值抑制。
  4. 双阈值筛选。

下面我来介绍一下这四步

1. 高斯滤波

在前面的文章里历经详细介绍了高斯滤波,遗忘的同学,链接如下:

10篇--图像噪点消除-CSDN博客

之前提到过,低通滤波器是模糊,高通滤波器是锐化

而边缘检测本身属于锐化操作,对噪点比较敏感,需要进行平滑处理。所以用到的高斯滤波高通滤波器。这里使用的是一个5*5的高斯核对图像进行消除噪声:

2. 计算图像的梯度与方向 

2.1 计算梯度

这里使用了Sobel算子(核值固定的卷积核)来计算图像的梯度值,如下所示:

这些是高数中二阶偏导数相关的概念,就不做赘述了。不理解也没关系,重点不在这,接着往下看

2.2 计算方向 

这个角度值其实就是当前边缘的梯度的方向,与边缘的方向刚好垂直。

通过这个公式我们就可以计算出图片中所有的像素点的梯度值与梯度方向,然后根据梯度方向获取边缘的方向,获得θ。得到θ的值之后,就可以对边缘方向进行分类,一般将其归为四个方向:

水平方向、垂直方向、45°方向、135°方向:

  • 当θ值为-22.5°~22.5°,或-157.5°~157.5°,则认为边缘为水平边缘;
  • 当法线方向为22.5°~67.5°,或-112.5°~-157.5°,则认为边缘为45°边缘;
  • 当法线方向为67.5°~112.5°,或-67.5°~-112.5°,则认为边缘为垂直边缘;
  • 当法线方向为112.5°~157.5°,或-22.5°~-67.5°,则认为边缘为135°边缘;

 3. 非极大值抑制

通过上面的操作,已经初步筛选出了边缘,把他们连起来不久OK了,齐活?

NO,NO,NO!本系列第10篇提到过,锐化都容易损坏边缘信息,使边缘模糊,导致经过第二步后得到的边缘像素点非常多,因此我们需要对其进行一些过滤操作。其中非极大值抑制就是一个很好的方法。

在边缘检测中,非极大值抑制的主要目的是细化边缘。具体来说,它通过对梯度图像中的像素值进行比较和筛选,只保留梯度方向上局部最大的像素值,而将其他非最大的像素值抑制为零。这样,边缘就变得更加细化和清晰,减少了冗余的边缘信息。假设当前像素点为(x,y),其梯度方向是0°,梯度值为G(x,y),那么我们就需要比较G(x,y)与两个相邻像素的梯度值:G(x-1,y)和G(x+1,y)。如果G(x,y)是三个值里面最大的,就保留该像素值,否则将其抑制为零。

并且如果梯度方向不是0°、45°、90°、135°这种特定角度,那么就要用到插值算法来计算当前像素点在其方向上进行插值的结果了,然后进行比较并判断是否保留该像素点。这里使用的是单线性插值,通过A1和A2两个像素点获得dTmp1与dTmp2处的插值,然后与中心点C进行比较。

4. 双阈值筛选

经过非极大值抑制之后,我们还需要设置阈值来进行筛选。

  • 当阈值设的太低,就会出现假边缘
  • 而阈值设的太高,一些较弱的边缘就会被丢掉

因此使用了双阈值来进行筛选,推荐高低阈值的比例为2 : 1到3 : 1之间,其原理如下图所示: 

  • 当某一像素位置的幅值超过最高阈值时,该像素必是边缘像素;
  • 幅值处于最高像素与最低像素之间时,如果它能连接到一个高于阈值的边缘时,则被认为是边缘像素,否则就不会被认为是边缘;
  • 当幅值低于最低像素时,该像素必不是边缘像素。

也就是说,上图中的A和C是边缘,B不是边缘。因为C虽然不超过最高阈值,但其与A相连,所以C就是边缘。

至此,Canny边缘检测就完成了。

 cv2.Canny()函数

功能:用于边缘检测的函数

参数:

  • ‌image‌: 输入图像,它应该是一个灰度图像(单通道)。
  • ‌threshold1‌: 第一个阈值,用于边缘检测的滞后过程。这个值较低,用于确定边缘的初始点。
  • ‌threshold2‌: 第二个阈值,用于边缘检测的滞后过程。这个值较高,用于确定边缘的最终点。如果某个像素点的梯度值高于这个阈值,它被认为是边缘;如果低于这个值但高于threshold1,并且与高于threshold2的像素点相连,它也被认为是边缘。
  • ‌edges‌: 输出图像,与输入图像大小相同,但通常是二值图像(即只包含边缘和非边缘的像素)。
  • ‌apertureSize‌(可选,默认为3): Sobel算子的大小,它决定了梯度计算的邻域大小。它必须是1、3、5或7之一。
  • ‌L2gradient‌(可选,默认为False): 一个布尔值,指示是否使用更精确的L2范数进行梯度计算。如果为True,则使用L2范数(即欧几里得距离);如果为False,则使用L1范数(即曼哈顿距离)。L2范数通常更精确,但计算成本也更高。

示例代码

import cv2

img = cv2.imread("kabuto.jpg")

# 灰度化
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 二值化
_, img_binary = cv2.threshold(img_gray, 127, 255,
                              cv2.THRESH_BINARY + cv2.THRESH_OTSU)

# 进行高斯滤波
img_blur = cv2.GaussianBlur(img_binary, (3,3), 3)

# 边缘检测
img_canny = cv2.Canny(img_blur, 10, 70)

cv2.imshow('img', img)
cv2.imshow('img_canny', img_canny)
cv2.waitKey(0)

效果对比 

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

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

相关文章

细说STM32F407单片机轮询方式读写SPI FLASH W25Q16BV

目录 一、工程配置 1、时钟、DEBUG 2、GPIO 3、SPI2 4、USART6 5、NVIC 二、软件设计 1、FALSH &#xff08;1&#xff09;w25flash.h &#xff08;2&#xff09; w25flash.c 1&#xff09;W25Q16基本操作指令 2&#xff09;计算地址的辅助功能函数 3&#xff09;器…

.net core在linux导出excel,System.Drawing.Common is not supported on this platform

使用框架 .NET7 导出组件 Aspose.Cells for .NET 5.3.1 asp.net core mvc 如果使用Aspose.Cells导出excel时&#xff0c;报错 &#xff1a; System.Drawing.Common is not supported on this platform 平台特定实现&#xff1a; 对于Windows平台&#xff0c;System.Drawing.C…

岁末回望,追梦远方

又到了岁末年初&#xff0c;按惯例&#xff0c;风云我都会写一篇长长的感悟&#xff0c;给自己辞旧的总结复盘&#xff0c;迎新的追梦定调&#xff0c;今年赋诗一首&#xff0c;畅想一下诗和远方&#xff0c;简洁而又虚无&#xff0c;缥缈中坚定初心。 岁末回首步履深&#xf…

作业Day4: 链表函数封装 ; 思维导图

目录 作业&#xff1a;实现链表剩下的操作&#xff1a; 任意位置删除 按位置修改 按值查找返回地址 反转 销毁 运行结果 思维导图 作业&#xff1a;实现链表剩下的操作&#xff1a; 1>任意位置删除 2>按位置修改 3>按值查找返回地址 4>反转 5>销毁 任意…

多个Echart遍历生成 / 词图云

echart官网 安装 如果版本报错推荐安装以下版本 npm install echarts4.8.0 --savenpm uninstall echarts//这个是卸载命令以下安装成功后是局部引入:多个Echart遍历生成 vue3echart单个页面多个图表循环渲染展示:<template><div class"main"><div …

混凝土-钢板结构抗剪性能DIC全场应变测试

混凝土-钢板结构发挥了钢板抗拉及混凝土抗压的特点&#xff0c;为建筑设计、选材、施工等过程带来了更多的可能性。构件将混凝土与钢板结合&#xff0c;从而改善抗剪承载性能&#xff0c;提升建筑性能。 采用3D-DIC非接触式三维全场应变测量技术&#xff0c;对构件的抗剪承载力…

网络安全渗透有什么常见的漏洞吗?

弱口令与密码安全问题 THINKMO 01 暴力破解登录&#xff08;Weak Password Attack&#xff09; 在某次渗透测试中&#xff0c;测试人员发现一个网站的后台管理系统使用了非常简单的密码 admin123&#xff0c;而且用户名也是常见的 admin。那么攻击者就可以通过暴力破解工具&…

音频开发中常见的知识体系

在 Linux 系统中&#xff0c;/dev/snd 目录包含与声音设备相关的文件。每个文件代表系统中的一部分音频硬件或音频控制接口。以下是你列出的文件及其含义&#xff1a; 一.基本术语 样本长度(sample)&#xff1a;样本是记录音频数据最基本的单位&#xff0c;计算机对每个通道采…

Linux setfacl 命令详解

文章目录 Linux setfacl 命令详解一、ACL 和 setfacl 简介二、基本语法三、常用操作1. 查看 ACL2. 为用户设置权限3. 为组设置权限4. 删除 ACL 条目5. 设置默认 ACL6. 递归设置 ACL 四、示例操作1. 创建示例目录和文件2. 设置 ACL3. 验证 ACL 五、注意事项六、总结 Linux setfa…

编程训练系统(代码+数据库+LW)

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了编程训练系统的开发全过程。通过分析编程训练系统管理的不足&#xff0c;创建了一个计算机管理编程训练系统的方案。文章介绍了编程训练系统的系统分析部分&…

提炼关键词的力量:AI驱动下的SEO优化策略

内容概要 在当今数字化营销的环境中&#xff0c;关键词对于提升网站的可见性和流量起着至关重要的作用。企业和个人必须重视有效的关键词策略&#xff0c;以便在竞争激烈的网络市场中脱颖而出。本文将深入探讨如何利用人工智能技术来优化SEO策略&#xff0c;特别是在关键词选择…

【Where语法全解密】.NET开源ORM框架 SqlSugar 系列

文章目录 前言一、普通表达式查询 Where二、根据SQL查询 where三、动态查询四、动态拼表达式查询 &#xff0c;拼拉姆达五、条件拼接查询六、链式条件查询七、根据Class查询&#xff0c;根据实查询八、根据Class中主键查询九、根据字典查询十、查询函数十一、Where中有子查询十…

模型优化之知识蒸馏

文章目录 知识蒸馏优点工作原理示例代码 知识蒸馏优点 把老师模型中的规律迁移到学生模型中&#xff0c;相比从头训练&#xff0c;加快了训练速度。另一方面&#xff0c;如果学生模型的训练精度和老师模型差不多&#xff0c;相当于得到了规模更小的学生模型&#xff0c;起到模…

电脑问题4[非华为电脑安装华为电脑管家华为荣耀手机多屏协助]

非华为电脑安装华为电脑管家华为荣耀手机多屏协助 我是荣耀手机之前一直用的是window的"连接手机"功能,电脑控制手机还蛮好用,但是又不能够没有好的电脑控制手机的功能,后来想了想看了看,竟然安装了华为电脑关键,竟然可以顺利连接上荣耀手机,发现还蛮好用! 本文引用…

win11 C盘出现感叹号解决方法

出现感叹号&#xff0c;原因是对C盘进行了BitLocker驱动器加密操作。如果想去除感叹号&#xff0c;对C盘进行BitLocker解密即可。 步骤如下&#xff1a; 1.点击Windows搜索框 2.搜索框内输入 系统 3.按下回车&#xff0c;进入系统界面 4.点击隐私和安全性 点击BitLocker驱…

MyBatis通过注解配置执行SQL语句原理源码分析

文章目录 前置准备流程简要分析配置文件解析加载 Mapper 接口MapperAnnotationBuilder解析接口方法注解parseStatement 方法详解MapperBuilderAssistant 前置准备 创建一个mybatis-config.xml文件&#xff0c;配置mapper接口 <mappers><!--注解配置--><mapper…

[数据结构] 链表

目录 1.链表的基本概念 2.链表的实现 -- 节点的构造和链接 节点如何构造? 如何将链表关联起来? 3.链表的方法(功能) 1).display() -- 链表的遍历 2).size() -- 求链表的长度 3).addFirst(int val) -- 头插法 4).addLast(int val) -- 尾插法 5).addIndex -- 在任意位置…

计算机基础 试题

建议做的时候复制粘贴,全部颜色改为黑色,做完了可以看博客对答案。 一、单项选择题(本大题共25小题,每小题2分,共50分〉 1.计算机内部采用二进制数表示信息,为了便于书写,常用十六进制数表示。一个二进制数0010011010110用十六进制数表示为 A.9A6 B.26B C.4D6 D.…

设计模式12:状态模式

系列总链接&#xff1a;《大话设计模式》学习记录_net 大话设计-CSDN博客 参考&#xff1a;设计模式之状态模式 (C 实现)_设计模式的状态模式实现-CSDN博客 1.概述 状态模式允许一个对象在其内部状态改变时改变其行为。对象看起来像是改变了其类。使用状态模式可以将状态的相…

SmartX分享:NVMe-oF 介绍、SMTX ZBS 如何选择高性能场景解决方案与如何实现

目录 背景什么是 NVMe-oFZBS AccessiSCSI 与 iSERNMVe-oF 介绍NVMeNVMe-oFNVMe-oF 承载网络&#xff08;数据平面&#xff09; ZBS NVMe-oF 实现ZBS 接入策略ZBS 接入点分配策略性能测试 为什么要支持 RoCE引用 背景 前几篇文章&#xff0c;我们认识到了 SmartX 公司产品 SMTX…