Canny边缘检测原理

article/2025/9/23 19:38:58

一. Canny基本思想

1. 边缘检测

解析:边缘是对象和背景之间的边界,还能表示重叠对象之间的边界。边缘检测是图像分割的一部分,图像分割的目的是识别出图像中的区域。边缘检测是定位边缘像素的过程,而边缘增强是增加边缘和背景之间的对比度以便能够更清楚地看清边缘的过程。边缘跟踪是沿着边缘进行跟踪的过程,这个过程通常会把边缘像素采集到一个列表中,链码算法是边缘跟踪算法的一个特例。

2. 最优边缘准则 [1]

Canny边缘检测算子是John F. Canny于1986年开发出来的一个多级边缘检测算法。Canny的目标是找到一个最优的边缘检测算法,最优边缘检测的含义,如下所示:

[1]最优检测:算法能够尽可能多地标识出图像中的实际边缘,漏检真实边缘的概率和误检非边缘的概率都尽可能小;

[2]最优定位准则:检测到的边缘点的位置距离实际边缘点的位置最近,或者是由于噪声影响引起检测出的边缘偏离物体的真实边缘的程度最小;

[3]检测点与边缘点一一对应:算子检测的边缘点与实际边缘点应该是一一对应。

二. Canny算法实现

1. 高斯滤波图像去噪

垃圾进,垃圾出,数据预处理工作是非常重要的,图像处理也不例外。这里使用高斯滤波进行图像去噪,比如blur = cv2.GaussianBlur(img, (5,5), 0),处理后的图像与原始图像相比稍微有些模糊。这样单独的一个像素噪声在经过高斯滤波的图像上变得几乎没有影响。

2. 计算图像梯度

Canny算法的基本思想是找寻一幅图相中灰度强度变化最强的位置。所谓变化最强,即指梯度方向。对平滑后的图像使用Sobel算子计算水平方向和竖直方向的一阶导数[图像梯度][]。根据得到的这两幅梯度图()找到边界的梯度和方向。如下所示:

梯度的方向一般总是与边界垂直。梯度方向被归为四类:垂直,水平,和两个对角线。

3. 非极大值抑制

在获得梯度的方向和大小之后,应该对整幅图像做一个扫描,去除那些非边界上的点。对每一个像素进行检查,看这个点的梯度是不是周围具有相同梯度方向的点中最大的。如下所示:

上图中的数字代表了像素点的梯度强度,箭头方向代表了梯度方向。以第二排第三个像素点为例,由于梯度方向向上,则将这一点的强度[7]与其上下两个像素点的强度[5和4]比较,由于这一点强度最大,则保留。

4. 滞后阈值

现在要确定那些边界才是真正的边界。这时我们需要设置两个阈值:minVal和maxVal。当图像的灰度梯度高于maxVal时被认为是真的边界,那些低于minVal的边界会被抛弃。如果介于两者之间的话,就要看这个点是否与某个被确定为真正的边界点相连,如果是就认为它也是边界点,如果不是就抛弃。如下所示:

A高于阈值maxVal所以是真正的边界点,C虽然低于maxVal但高于minVal并且与A相连,所以也被认为是真正的边界点。而B就会被抛弃,因为它不仅低于maxVal而且不与真正的边界点相连。所以选择合适的maxVal和minVal对于能否得到好的结果非常重要。在这一步一些小的噪声点也会被除去,因为我们假设边界都是一些长的线段。

三. Canny代码应用

import cv2
import numpy as npif __name__ == '__main__':def nothing(*arg):passcv2.namedWindow('edge')cv2.createTrackbar('thrs1', 'edge', 2000, 5000, nothing)cv2.createTrackbar('thrs2', 'edge', 4000, 5000, nothing)cap = cv2.VideoCapture(0)while True:flag, img = cap.read()img = cv2.GaussianBlur(img, (3,3), 0) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)thrs1 = cv2.getTrackbarPos('thrs1', 'edge')thrs2 = cv2.getTrackbarPos('thrs2', 'edge')edge = cv2.Canny(gray, thrs1, thrs2, apertureSize=5)vis = img.copy()vis = np.uint8(vis/2.)vis[edge != 0] = (0, 255, 0)cv2.imshow('edge', vis)ch = cv2.waitKey(5) & 0xFFif ch == 27:breakcv2.destroyAllWindows()

解析:

1. cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient]]]) → edges

[1]其中较大的threshold2用于检测图像中明显的边缘,但一般情况下检测的效果不会那么完美,边缘检测出来是断断续续的,所以这时候用较小的threshold1用于将这些间断的边缘连接起来。

[2]可选参数apertureSize是Sobel算子的大小[默认值为3],而参数L2gradient是一个布尔值,如果为真,则使用更精确的L2范数进行计算[即两个方向的倒数的平方和再开方],否则使用L1范数[直接将两个方向导数的绝对值相加]。

2. cv2.Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]]) → dst

[1]ddepth表示图像的深度,-1表示采用的是与原图像相同的深度。目标图像的深度必须大于等于原图像的深度;

[2]dx和dy表示求导的阶数,0表示这个方向上没有求导,一般为0、1、2。

[3]ksize表示Sobel算子的大小,必须为1、3、5、7。

[4]scale:optional scale factor for the computed derivative values; by default, no scaling is applied。

[5]delta:optional delta value that is added to the results prior to storing them in dst.

[6]borderType:pixel extrapolation method.

3. cv2.convertScaleAbs(src[, dst[, alpha[, beta]]]) → dst

[1]Scales, calculates absolute values, and converts the result to 8-bit, namely dst = src*alpha + beta.
[2]alpha:optional scale factor.
[3]beta:optional delta added to the scaled values.

4. cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]]) → dst

[1]alpha表示src1的权重。

[2]beta表示src2的权重。

[3]gamma:scalar added to each sum.

[4]dtype:optional depth of the output array; when both input arrays have the same depth, dtype can be set to -1, which will be equivalent to src1.depth().

cv2.addWeighted表示计算两个数组的权重和,即dst = src1*alpha + src2*beta + gamma。

说明:边缘检测常用方法:Canny算子,Sobel算子,Laplace算子,Scharr滤波器。

参考文献:

[1] Canny算法:canny算法_百度百科

[2] OpenCV官方教程中文版

[3] OpenCV-Python教程:OpenCV-Python教程(6、Sobel算子)_Daetalus的博客-CSDN博客


http://chatgpt.dhexx.cn/article/ewHHbv3w.shtml

相关文章

Canny边缘检测

边缘检测发展 Canny 边缘检测是一种从不同视觉对象中提取有用结构信息并显着减少要处理的数据量的技术。它已广泛应用于各种计算机视觉系统。 Canny 发现,在不同的视觉系统上应用边缘检测的要求是比较相似的。因此,可以在各种情况下实施满足这些要求的边…

Canny边缘检测算法(python 实现)

文章目录 最优边缘准则算法实现步骤1. 应用高斯滤波来平滑(模糊)图像,目的是去除噪声2. 计算梯度强度和方向3. 应用非最大抑制技术NMS来消除边误检4. 应用双阈值的方法来决定可能的(潜在的)边界5. 利用滞后技术来跟踪边界 opencv实现Canny边缘…

左外连接和右外连接是什么样的?

1左外连接 左表的记录都会出现在结果集中,并上右表与之对应的部分,如果右表没有,使用null填充。 举例。 select * from people p left join role r p.idr.id 左外连接结果: 2、右外连接 右表的记录都会出现在结果集中&#xf…

sql左外连接和右外连接的区别

一、数据集合不同 1、左外连接:是A和B的交集再并上A的所有数据。 2、右外连接:是A和B的交集再并上B的所有数据。 二、语法不同 1、左外连接:SELECT *FROM aLEFT OUTER JOIN bON a.ageId b.id。 2、右外连接:SELECT *FROM a…

MySQL自连接和内连接和外连接_左外连接+右外连接

自连接:将一张表看作两张表 练习:查询员工id,员工姓名及其管理者的id和姓名select emp.employee_id,emp.last_name,mgr.employee_id,mgr.last_name from employees emp,employees mgr where emp.manager_id mgr.employee_id;内连接 只是把左…

SQL--左外连接(LEFT JOIN)

LEFT JOIN 关键字从左表(table1)返回所有的行,即使右表(table2)中没有匹配。如果右表中没有匹配,则结果为 NULL。 SQL LEFT JOIN 语法: SELECT column_name(s) FROM table1 LEFT JOIN table2 ON table1.c…

内连接、左连接、左外连接、右连接的区别

一:测试例子 存在如下两张表:年级与班级,表内容如下 班级表 二:内连接与自然连接 1:自然连接 对于select * from gradeclass gc where gc.grade_id in (select id from grade),其结果如下图 其查询是把符…

数据库之SQL(基本连接,内连接,左外连接,右外连接,全外连接,交叉连接,自连接)

之前的博客内容我们分享了数据表的查询与管理,但那只是针对数据库中的一个表格进行的查询管理,现在如果我们想要同时看到两个数据表中的数据的话,那要怎么办呢?采用多连接查询的方式。 SQL中有哪几种多连接的方式? 有七…

左连接、右连接、内连接、外连接简单说明

例如有两个表: test1: test2: 内连接:(inner join on)返回两个表的交集。 例如: select * from test1 a inner join test2 b on a.idb.id; 结果: 外连接:返回两个表的并集。(在此就不做截图…

MySQL之左外连接右外连接

外连接: 假设A和B表进行连接,使用外连接的话, AB两张表中有一张表是主表,一张表是副表,主要查询主表中的数据,捎带着查询副表, 当副表中的数据没有和主表中的数据匹配上,副表自动模…

秒懂sql中的左外连接

左外连接: 1.语法: SELECT 查询字段 FROM 查询表格(左表) LEFT JOIN 右表 ON 查询条件 2.左外连接查询的就是左表,那干嘛加个右表,岂不是没有作用: 区别在于左外连接是查询完左表后&…

sql的四种连接——左外连接、右外连接、内连接、全连接

一、内连接 满足条件的记录才会出现在结果集中。 二、 左外连接(left outer join,outer可省略) 左表全部出现在结果集中,若右表无对应记录,则相应字段为NULL 举例说明: 客户表: 订单表&#x…

数据库的内连接、外连接(左外连接、右外连接、全外连接)以及交叉连接

SQL数据库的连接:内连接、和外连接(左外连接、右外连接、和全连接) 本次实验在MySQL数据库中进行,数据库初始表如下: 一、内连接:结果仅包含符合连接条件的两表中的行。如下: 二、外连接&#…

oracle左外连接、右外连接、完全外连接以及(+)号用法

准备工作 oracle连接分为: 左外连接:左表不加限制,保留左表的数据,匹配右表,右表没有匹配到的行中的列显示为null。右外连接:右表不加限制,保留右表的数据。匹配左表,左表没有匹配到…

左连接,右链接

用两个表(a_table、b_table),关联字段a_table.a_id和b_table.b_id来演示一下MySQL的内连接、外连接( 左(外)连接、右(外)连接、全(外)连接)。 MySQL版本:Server version: 5.6.31 MySQL Community Server (…

全外连接、左外连接和右外连接区别(含举例)

全外连接是左外连接和右外连接的结合。 左外连接和右外连接的区别如下: 1、数据集合上的区别 (1)左外连接:是A与B的交集,然后连接A的所有数据。 (2)右外连接:是A与B的交集&#xff…

连接查询之外连接(左外链接和右外连接)

内连接: 假设A表和B表进行连接查询,使用内连接的话,凡是A表和B表能够匹配上的记录被查询出来,这就是内连接。A、B两张表没有主副之分,两张表是平等的。 外连接: 假设A表和B表进行连接查询,使用…

左连接、右连接、内连接、外连接

一.外连接 外连接分三类:左外连接(LEFT OUTER JOIN)、右外连接(RIGHT OUTER JOIN)和全外连接(FULL OUTER JOIN)。 1.左外连接 左连接 left join 是left outer join的简写,left j…

左外连接和右外连接的含义及区别,举例说明

左连接的含义是限制表2中的数据必须满足连接条件,而不管表1中的数据是否满足连接条件,均输出表1的内容。 右连接的含义是限制表1中的数据必须满足连接条件,而不管表2中的数据是否满足连接条件,均输出表2的内容。 创建表格A1,B1,…

外连接(左连接和右连接)

介绍: 1.内连接:两张表没有主次关系;外连接:两张表产生了主次关系 2.带有right的是右外连接,又叫右连接;带有left的是左外连接,又叫左连接 3.任何一个左连接都有右连接的写法,任何…