Canny 边缘检测及相关应用
该内容为
- 《学习图像局部特征检测和描述-基于OpenCV源码分析的算法与实现》
- 《OpenCV 3 计算机视觉-Python语言实现》
- OpenCV官方网站的 https://docs.opencv.org/master/da/d22/tutorial_py_canny.html
的学习内容
1 Canny 边缘检测理论分析
Canny 边缘检测方法是由 Canny 于1996 年提出的一种公认为效果较好的边缘检测方法。
一个好的边缘检测方法应该满足三项指标
- 1、低失误率,即不能漏检也不能错检
- 2、高的位置精度,标定的边缘像素点与真正的边缘中心之间距离应该最小
- 3、每个边缘应该由唯一的响应,即得到单像素宽度的边缘。
基于此,Canny提出了判定边缘检测算子的3个准则:
- 1 - 信噪比准则
- 2 - 定位精度准则
- 3 - 单边缘响应准则
Canny 算子实现过程共有4(5)个步骤:
- 1 - 平滑处理,使用高斯滤波器对图像进行去噪处理
- 2 - 寻找图像的强度梯度 / 计算梯度 / 梯度检测
- 3 - 非极大值抑制,即在图像边缘上使用非最大抑制NMS
- 4 - 滞后阈值处理,即在检测到的边缘上使用双阈值去除假阳性(false positive)
- 5 - 最后分析所有边缘及其之间的连接,以确保保留真正的边缘,同时消除不明显的边缘
1.1 Canny算子实现过程详细讲解
1.1.1 平滑处理
所有的边缘都极易受到噪声的干扰,为防止检测结果的偏差较大,有必要使用平滑滤波的方法滤除噪声。高斯滤波方法是常用的滤波方法,二维图像应用二维高斯函数,它的定义为
式中 σ 表示 高斯函数的标准差。只要把输入图像与二维高斯函数进行卷积,即可得到平滑后的图像。
注:
考虑到数字图像为离散化的形式,我们往往把高斯函数转化为离散化的高斯内核模板形式,如标准差为1.4 的模板尺寸为 5 * 5 的归一化高斯内涵模板为:
1.1.2 寻找图像的强度梯度 Finding Intensity Gradient of the Image
寻找图像的强度梯度 / 计算梯度 / 梯度检测
梯度是图像灰度值变化剧烈的地方,它可以通过 Roberts 算子、Prewitt 算子、Sobel 算子(最常用)等最简单的模板检测方法得到。
Sobel 算子是由两个模板组成:
,
这Sobel算子内核(的两个模板)分别在水平和垂直方向上对平滑后的图像进行滤波,以获得水平方向的梯度 Gx 和 垂直方向的梯度 Gy (注:该处的梯度也可称为一阶导数),最终图像每个像素的边缘梯度 Edge_Gradient 和方向,通常采用欧几里计算方法得边缘梯度幅值(L2范数):
但平时为了简化,梯度值也可由曼哈顿距离(L1范数)求得:
梯度幅角 θ 为:
注:由该公式得到得梯度幅角是任意值,但我们需要将其四舍五入到表示垂直、水平和两个对角线方向的四个角度中的一个,共计 4 个方向 !即 0°、45°、90°、135°;如梯度幅角为(-22.5,22.5)区间值时,均会四舍五入为 0° 。
1.1.3 非最大抑制 Non-maximum Suppression
非最大值抑制也成为非极大值抑制
该步骤的目的是使边缘细化。
梯度检测后获得的图像边缘较为模糊,不合符 “ 好的边缘检测 ” 中的第三项:
- 3、每个边缘应该由唯一的响应,即得到单像素宽度的边缘。
也即,在获得梯度幅度和方向之后,需要完成图像的全扫描以去除可能不构成边缘的任何不需要的像素。为此,在每个像素处,检查像素是否是其在梯度方向上的邻域中的局部最大值。保留具有局部最大值的像素点即为灰度值变化最剧烈的地方,如下图所示
上图中 A 点位于边缘(垂直方向),其渐变方向与边缘垂直;B 点和 C 点处于梯度方向。按照非最大值抑制思路,用点 B 和 C 检查点 A ,看 A 点是否形成局部最大值,若是最大值,it is considered for next stage,若不是局部最大值,A点将会被抑制,即归零 put to zero。最终目的是得到 “ 细边 ” 单像素的二进制图像。
注:这里局部最大值是由在 3*3 的邻域内的梯度方向上比较梯度值得到的。
1.1.4 滞后阈值 Hysteresis Thresholding
该步骤是决定那些边缘是边缘,那些边缘不是边缘。
上步骤得到的边缘仍存在有 ” 假边缘 “,这是由于噪声或颜色变化的影响而产生的非真正边缘。
这种现象的表现形式是尽管这些边缘的梯度幅值是局部最大值,但与其他边缘比,它们的梯度幅值很小,也就是绝对梯度幅值很小。
为此,我们采用滞后阈值处理法。
设置 minVal 和 maxVal 两个阈值,
- 强度梯度大于 maxVal 的任何边缘肯定是边缘(强边缘),将被保留
- 强度梯度小于 minVal 的任何边缘肯定是非边缘(非边缘),因此被丢弃。
- 强度梯度介于 maxVal 和 minVal 之间的边缘为弱边缘,通过进一步计算决定弱边缘的去留。
具体去留方式算法如下:
边缘 A 高于 maxVal,因此被视为 ” 确定边缘(sure-edge) “ ;虽然边(缘)C 低于 maxVal,但是它连接到边(缘) A,因此被视为有效边(缘),我们可获得完成的曲线。对于边缘 B 而言,其虽然高于 minVal,但它没有连接到任何 ”确定边缘(sure-edge)“,同时又与边缘 C 区域相同,因此将被丢弃。该方法也就是所谓的 ” 边缘跟踪 “ 法来判断弱边缘是否为真正的边缘。
具体计算为:在弱边缘的 3*3 区域内,若有强边缘,则说明该弱边缘是属于这个强边缘的,将被保留,否则将被丢弃。
所以我们最终得到的是图像中的强边缘(strong edges in the image.)。
2 码源分析
Canny 函数的原型为:
Python: edges = cv.Canny( image,#input 单通道8-bit灰度图, threshold1,#滞后阈值法中低阈值minVal threshold2,#滞后阈值法中低阈值maxVal [edges],#output边缘图,单通道8位图,与image大小相同 [apertureSize],#孔径尺寸,即Sobel算子的尺寸大小,默认值为3 [L2gradient]#计算梯度幅值L1、L2范数选择,默认False(L2范式 ) )
OpenCV中的Canny算法的码源:略
注意:
1、由于 OpenCV 中 没有执行经典 Canny 方法中的第一步,即省去了滤波平滑;所有我们需要事前进行平滑处理。
2、OpenCV 中的 Canny 算法仅遍历了一遍图像,就完成了步骤2(梯度计算)和步骤3(非最大值抑制);具体过程是计算当前遍历行的梯度幅值,同时计算前一行的梯度幅角,并完成 3*3 邻域内的非最大值抑制。
3、步骤3(非最大值抑制)和步骤4(滞后阈值处理)是交错在一起计算的。
4、步骤4 中的边缘追踪法中,程序是寻找强边缘的 3*3 邻域内的弱边缘的方法,而不是寻找弱边缘的 3*3 邻域内的强边缘。
3 简单示例
import numpy as np import cv2 as cv from matplotlib import pyplot as plt img = cv.imread('img.jpg',0) edges = cv.Canny(img,100,200) 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()
来源:Canny Edge Detection(4.0.1) 版本 https://docs.opencv.org/master/da/d22/tutorial_py_canny.html
运行效果:
4 车道线检测(实际项目)
略
Canny 边缘检测及相关应用的更多相关文章
- OpenCV: Canny边缘检测算法原理及其VC实现详解(转载)
原文地址:http://blog.csdn.net/likezhaobin/article/details/6892176 原文地址:http://blog.csdn.net/likezhaobin/ ...
- 学习笔记-canny边缘检测
Canny边缘检测 声明:阅读本文需要了解线性代数里面的点乘(图像卷积的原理),高等数学里的二元函数的梯度,极大值定义,了解概率论里的二维高斯分布 1.canny边缘检测原理和简介 2.实现步骤 3. ...
- 【算法随记】Canny边缘检测算法实现和优化分析。
以前的博文大部分都写的非常详细,有很多分析过程,不过写起来确实很累人,一般一篇好的文章要整理个三四天,但是,时间越来越紧张,后续的一些算法可能就以随记的方式,把实现过程的一些比较容易出错和有价值的细节 ...
- Canny边缘检测算法原理及其VC实现详解(二)
转自:http://blog.csdn.net/likezhaobin/article/details/6892629 3. Canny算法的实现流程 由于本文主要目的在于学习和实现算法,而对于图像 ...
- OpenCV笔记(3)(Canny边缘检测、高斯金字塔、拉普拉斯金字塔、图像轮廓、模板匹配)
一.Canny边缘检测 Canny边缘检测是一系列方法综合的结果.其中主要包含以下步骤: 1.使用高斯滤波器,平滑图像,滤除噪声. 2.计算图像中每个像素点的梯度强度和方向. 3.应用非极大值抑制(N ...
- Canny边缘检测
1.Canny边缘检测基本原理 (1)图象边缘检测必须满足两个条件:一能有效地抑制噪声:二必须尽量精确确定边缘的位置. (2)根据对信噪比与定位乘积进行测度,得到最优化逼近算子.这 ...
- OpenCV图像Canny边缘检测
Canny边缘检测 图像的边缘检测的原理是检测出图像中所有灰度值变化较大的点,而且这些点连接起来就构成了若干线条,这些线条就可以称为图像的边缘函数原型: void cvCanny( ...
- 从视频文件中读入数据-->将数据转换为灰度图-->对图像做canny边缘检测-->将这三个结构显示在一个图像中
//从视频文件中读入数据-->将数据转换为灰度图-->对图像做canny边缘检测-->将这三个结构显示在一个图像中 //作者:sandy //时间:2015-10-10 #inclu ...
- [转载+原创]Emgu CV on C# (六) —— Emgu CV on Canny边缘检测
Canny边缘检测也是一种边缘检测方法,本文介绍了Canny边缘检测的函数及其使用方法,并利用emgucv方法将轮廓检测解算的结果与原文进行比较. 图像的边缘检测的原理是检测出图像中所有灰度值变化较大 ...
随机推荐
- 589. N叉树的前序遍历
[题目] 给定一个 N 叉树,返回其节点值的前序遍历. 例如,给定一个 3叉树 : 返回其前序遍历: [1,3,5,6,2,4]. [解析] """ # Definiti ...
- BOM 和 DOM
目录 一.BOM 1.什么是BOM 2. 浏览器内容划分 归BOM管的: 归DOM管的: 3. BOM常见方法 二.DOM 1 什么是DOM 2. DOM常见方法 一.BOM 1.什么是BOM BOM ...
- Jenkins环境搭建(3)-配置自动发送邮件
紧接上一篇博文继续来完善Jenkins自动构建环境的搭建,今天来分享下配置邮件,构建任务后,自动发送邮件到指定邮箱 配置邮件分为两部分,第一部分是在系统管理中的系统设置中配置,第二部分是在任务中配置 ...
- NIO编程---通道(Channel)
**版权声明:本文为小斑马伟原创文章,转载请注明出处! 通道(Channel):由java.nio.channels 包定义的.Channel 表示IO 源与目标打开的连接.Channel 类似于传统 ...
- CSS选择器、样式、盒模型
一.CSS基础选择器 # 1.*(通配选择器):html,body以及body下用于显示的标签 #html和body颜色会被改变,但是div标签不会发生改变,由于不同的选择器具有优先级 # 语法:* ...
- POJ2386----Lake Counting
/* 利用宽搜将每块积水填满,添加一个计数器,记下填满几块积水即答案 */ #include<iostream> using namespace std; ][]; ][] = {{-,- ...
- 前后端通过API交互
前两篇已经写好了后端接口,和前段项目环境也搭建好了 现在要通过接口把数据展示在页面上 先占位置写架子 创建一个头部组件和底部组件占位置 <template> <h1>这是头部组 ...
- [转]REMOTE_ADDR,HTTP_CLIENT_IP,HTTP_X_FORWARDED_FOR
午睡一觉醒来,突然想伪造IP地址.搜了一下,Mark. 源地址:http://www.cnblogs.com/lmule/archive/2010/10/15/1852020.html ------- ...
- My Web Developer Roadmap
必需技能部分,可以理解为通用的.基础的技能,不管我们选择哪个方向都是通用的,包括但不限于 Git 使用.HTTP/HTTPS.数据结构和算法等.当然了,学习能力是必须具备的. 从一开始学习web前端, ...
- java项目中Excel文件的导入导出
package poi.excel; import java.io.IOException; import java.io.InputStream; import java.io.OutputStre ...