Opencv Canny边缘检测

devtools/2025/3/3 5:45:19/

边缘检测的目的是找到灰度值的突变

步骤:

  1. 使用高斯滤波,以平滑图像、滤除噪声
  2. 计算图像中每个像素点的梯度强度和方向
  3. 应用非极大值预测,以消除边缘检测的杂散响应
  4. 应用双阈值检测来确定真实的和潜在的边缘
  5. 通过抑制孤立的弱边缘最终完成边缘检测

5.1 高斯滤波器

H = [ 0.0924 0.1192 0.0924 0.1192 0.1538 0.1192 0.0924 0.1192 0.0924 ] H = \begin{bmatrix}0.0924 & 0.1192 & 0.0924 \\0.1192 & 0.1538 & 0.1192 \\0.0924 & 0.1192 & 0.0924\end{bmatrix} H= 0.09240.11920.09240.11920.15380.11920.09240.11920.0924

H H H为3×3高斯滤波器,经过归一化处理。
e = H ∗ A = [ h 11 h 12 h 13 h 21 h 22 h 23 h 31 h 32 h 33 ] ∗ [ a b c d e f g h i ] = sum ( [ a × h 11 b × h 12 c × h 13 d × h 21 e × h 22 f × h 23 g × h 31 h × h 32 i × h 33 ] ) e = H * A = \begin{bmatrix}h_{11} & h_{12} & h_{13} \\h_{21} & h_{22} & h_{23} \\h_{31} & h_{32} & h_{33}\end{bmatrix} * \begin{bmatrix}a & b & c \\d & e & f \\g & h & i\end{bmatrix} = \text{sum} \left( \begin{bmatrix}a \times h_{11} & b \times h_{12} & c \times h_{13} \\d \times h_{21} & e \times h_{22} & f \times h_{23} \\g \times h_{31} & h \times h_{32} & i \times h_{33}\end{bmatrix} \right) e=HA= h11h21h31h12h22h32h13h23h33 adgbehcfi =sum a×h11d×h21g×h31b×h12e×h22h×h32c×h13f×h23i×h33
A A A为图像区域,与高斯滤波器对应元素相乘后得到 e e e为滤除噪声后的结果矩阵。


5.2 梯度和方向

S x = [ − 1 0 1 − 2 0 2 − 1 0 1 ] S y = [ 1 2 1 0 0 0 − 1 − 2 − 1 ] S_x = \begin{bmatrix}-1 & 0 & 1 \\-2 & 0 & 2 \\-1 & 0 & 1\end{bmatrix}S_y = \begin{bmatrix}1 & 2 & 1 \\0 & 0 & 0 \\-1 & -2 & -1\end{bmatrix} Sx= 121000121 Sy= 101202101

这是Sobel算子的两个卷积核 S x S_{x} Sx S y S_{y} Sy
G x = S x ∗ A = [ − 1 0 1 − 2 0 2 − 1 0 1 ] ∗ [ a b c d e f g h i ] = sum ( [ − a 0 c − 2 d 0 2 f − g 0 i ] ) G y = S y ∗ A = [ 1 2 1 0 0 0 − 1 − 2 − 1 ] ∗ [ a b c d e f g h i ] = sum ( [ a 2 b c 0 0 0 − g − 2 h − i ] ) G_x = S_x * A = \begin{bmatrix}-1 & 0 & 1 \\-2 & 0 & 2 \\-1 & 0 & 1\end{bmatrix} * \begin{bmatrix}a & b & c \\d & e & f \\g & h & i\end{bmatrix} = \text{sum} \left( \begin{bmatrix}-a & 0 & c \\-2d & 0 & 2f \\-g & 0 & i\end{bmatrix} \right) \\G_y = S_y * A = \begin{bmatrix}1 & 2 & 1 \\0 & 0 & 0 \\-1 & -2 & -1\end{bmatrix} * \begin{bmatrix}a & b & c \\d & e & f \\g & h & i\end{bmatrix} = \text{sum} \left( \begin{bmatrix}a & 2b & c \\0 & 0 & 0 \\-g & -2h & -i\end{bmatrix} \right) Gx=SxA= 121000121 adgbehcfi =sum a2dg000c2fi Gy=SyA= 101202101 adgbehcfi =sum a0g2b02hc0i
计算x和y方向上的梯度,再计算总梯度和方向
G = G x 2 + G y 2 θ = arctan ⁡ ( G y G x ) G = \sqrt{G_x^2 + G_y^2}\\\theta = \arctan\left(\frac{G_y}{G_x}\right) G=Gx2+Gy2 θ=arctan(GxGy)

5.3 非极大值抑制

非极大值抑制目的是确保检测到的边缘是细的、连续的,并且尽可能地精确。这一步骤非极大值抑制能够有效地抑制非边缘点,保留真正的边缘点。

非极大值抑制有两种方法:

线性插值法

在这里插入图片描述

图中ABCDE每个点代表一个像素点,E点的梯度为蓝色的线,梯度方向指向左上角,边缘与梯度方向垂直。想确定这条梯度线上的边缘,就要比较E点的梯度和f、g点的梯度,而f、g点为亚像素点,所以f点需要通过A点与B点的梯度值求得。

f点的梯度值 = M(A)*w1+M(B)*w2,其中M表示梯度幅值,w1可等于L(Af)/L(AB),同理w2也是如此

同理,可求得g点的梯度值,从而比较三个点的梯度值,确定哪点最大该点与梯度值的垂直方向就是边缘。


梯度方向离散化

我们可以把一个像素的梯度方向离散化为八个方向,这样就只需计算前后即可,不需要插值

在这里插入图片描述

将每个像素的梯度方向分解为八个方向。假设梯度方向是45°,如果点 A 的梯度幅值大于其相邻像素点的梯度幅值,则保留点 A;否则,抑制点 A。


5.4 双阈值检测

梯度幅值大于高阈值的像素被标记为强边缘像素,而梯度幅值小于低阈值的像素被标记为非边缘像素。梯度幅值介于两者之间的像素被标记为弱边缘像素。

强边缘像素通常是确定的边缘,而弱边缘像素是否属于边缘则需要进一步判断。通常,低阈值设置为高阈值的一半。

在这里插入图片描述


代码实现Canny边缘检测:

img = cv2.imread('lena.jpg', cv2.IMREAD_GRAYSCALE)
# 传入图片数据和两个阈值
v1 = cv2.Canny(img, 80, 150)
v2 = cv2.Canny(img, 50, 100)res = np.hstack((v1, v2))
cv_show(res, 'res')

在这里插入图片描述

两个阈值越大,边缘的精确度就会提高,检测到的边缘就会减少,一些细节会丢失,也有可能会漏检真实的边缘。


http://www.ppmy.cn/devtools/164105.html

相关文章

4070Super安装GPU版本pytorch记录

一些啐啐念。 安装LLaMA-Factory时遇到pytorch安装成CPU版本。网上找了一圈攻略,都是下载龟速。挂梯子也一样。最后在尝试用pytorch官网的生成的命令进行安装时,突然奇想,直接把安装日志显示的下载链接复制到浏览器下载,发现可以满…

Rust Async 并发编程:处理任意数量的 Future

1. 使用 join! 处理多个未知数量的 Future 当我们只需要等待两个或三个异步任务完成时,可以使用 trpl::join、trpl::join3 或更通用的 join! 宏: join!(fut1, fut2, fut3);它们可以并行地等待多个异步任务完成,并将结果打包成一个元组。这对…

av_find_input_format 和 AVInputFormat 的关系

1. av_find_input_format 和 AVInputFormat 的关系 av_find_input_format 是 FFmpeg 中的一个函数,用于根据输入格式的名称(如 "mp4"、"wav"、"avfoundation" 等)查找对应的输入格式结构体 AVInputFormat。 …

LeetCode第58题_最后一个单词的长度

LeetCode 第58题:最后一个单词的长度 题目描述 给你一个字符串 s,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中最后一个单词的长度。 单词 是指仅由字母组成、不包含任何空格字符的最大子字符串。 难度 简单 题目链接 点…

Spring DIIoC

一.IoC 1.简介 什么是IoC?IoC,全称 Inversion of Control,控制反转。IoC是Spring的核心思想,Spring是⼀个“控制反转”的容器。 如果我们需要一个对象,正常来说我们是通过new一个对象,这个时候我们依赖的…

OptiTrack光学跟踪系统:引领工厂机器人应用的革新浪潮

在现代化的工厂生产线上,一台机械臂正以惊人的毫米级精度执行着精密零件的装配任务。这一精准操作的背后,是OptiTrack光学跟踪系统的实时捕捉与优化,它正助力生产效率与产品质量迈向新的高度。如今,这一技术正在全球范围内广泛应用…

【异地访问本地DeepSeek】Flask+内网穿透,轻松实现本地DeepSeek的远程访问

写在前面:本博客仅作记录学习之用,部分图片来自网络,如需引用请注明出处,同时如有侵犯您的权益,请联系删除! 文章目录 前言依赖Flask构建本地网页访问LM Studio 开启网址访问DeepSeek 调用模板Flask 访问本…

Spark技术系列(二):深入理解RDD编程模型——从原理到生产实践

Spark技术系列(二):深入理解RDD编程模型——从原理到生产实践 1. RDD设计哲学与核心定位 1.1 为什么需要RDD? MapReduce的缺陷:固定Map/Reduce阶段、中间数据频繁落盘、难以处理迭代计算RDD(Resilient Distributed Datasets)核心价值: 内存计算:中间结果缓存至内存,…