该内容为html
的学习内容算法
Canny 边缘检测方法是由 Canny 于1996 年提出的一种公认为效果较好的边缘检测方法。ide
一个好的边缘检测方法应该知足三项指标函数
基于此,Canny提出了断定边缘检测算子的3个准则:源码分析
Canny 算子实现过程共有4(5)个步骤:学习
全部的边缘都极易受到噪声的干扰,为防止检测结果的误差较大,有必要使用平滑滤波的方法滤除噪声。高斯滤波方法是经常使用的滤波方法,二维图像应用二维高斯函数,它的定义为网站
式中 σ 表示 高斯函数的标准差。只要把输入图像与二维高斯函数进行卷积,便可获得平滑后的图像。spa
注:3d
考虑到数字图像为离散化的形式,咱们每每把高斯函数转化为离散化的高斯内核模板形式,如标准差为1.4 的模板尺寸为 5 * 5 的归一化高斯内涵模板为:code
寻找图像的强度梯度 / 计算梯度 / 梯度检测
梯度是图像灰度值变化剧烈的地方,它能够经过 Roberts 算子、Prewitt 算子、Sobel 算子(最经常使用)等最简单的模板检测方法获得。
Sobel 算子是由两个模板组成:
,
这Sobel算子内核(的两个模板)分别在水平和垂直方向上对平滑后的图像进行滤波,以得到水平方向的梯度 Gx 和 垂直方向的梯度 Gy (注:该处的梯度也可称为一阶导数),最终图像每一个像素的边缘梯度 Edge_Gradient 和方向,一般采用欧几里计算方法得边缘梯度幅值(L2范数):
但平时为了简化,梯度值也可由曼哈顿距离(L1范数)求得:
梯度幅角 θ 为:
注:由该公式获得得梯度幅角是任意值,但咱们须要将其四舍五入到表示垂直、水平和两个对角线方向的四个角度中的一个,共计 4 个方向 !即 0°、45°、90°、135°;如梯度幅角为(-22.5,22.5)区间值时,均会四舍五入为 0° 。
非最大值抑制也成为非极大值抑制
该步骤的目的是使边缘细化。
梯度检测后得到的图像边缘较为模糊,不合符 “ 好的边缘检测 ” 中的第三项:
- 三、每一个边缘应该由惟一的响应,即获得单像素宽度的边缘。
也即,在得到梯度幅度和方向以后,须要完成图像的全扫描以去除可能不构成边缘的任何不须要的像素。为此,在每一个像素处,检查像素是不是其在梯度方向上的邻域中的局部最大值。保留具备局部最大值的像素点即为灰度值变化最剧烈的地方,以下图所示
上图中 A 点位于边缘(垂直方向),其渐变方向与边缘垂直;B 点和 C 点处于梯度方向。按照非最大值抑制思路,用点 B 和 C 检查点 A ,看 A 点是否造成局部最大值,如果最大值,it is considered for next stage,若不是局部最大值,A点将会被抑制,即归零 put to zero。最终目的是获得 “ 细边 ” 单像素的二进制图像。
注:这里局部最大值是由在 3*3 的邻域内的梯度方向上比较梯度值获得的。
该步骤是决定那些边缘是边缘,那些边缘不是边缘。
上步骤获得的边缘仍存在有 ” 假边缘 “,这是因为噪声或颜色变化的影响而产生的非真正边缘。
这种现象的表现形式是尽管这些边缘的梯度幅值是局部最大值,但与其余边缘比,它们的梯度幅值很小,也就是绝对梯度幅值很小。
为此,咱们采用滞后阈值处理法。
设置 minVal 和 maxVal 两个阈值,
具体去留方式算法以下:
边缘 A 高于 maxVal,所以被视为 ” 肯定边缘(sure-edge) “ ;虽然边(缘)C 低于 maxVal,可是它链接到边(缘) A,所以被视为有效边(缘),咱们可得到完成的曲线。对于边缘 B 而言,其虽然高于 minVal,但它没有链接到任何 ”肯定边缘(sure-edge)“,同时又与边缘 C 区域相同,所以将被丢弃。该方法也就是所谓的 ” 边缘跟踪 “ 法来判断弱边缘是否为真正的边缘。
具体计算为:在弱边缘的 3*3 区域内,如有强边缘,则说明该弱边缘是属于这个强边缘的,将被保留,不然将被丢弃。
因此咱们最终获得的是图像中的强边缘(strong edges in the image.)。
Canny 函数的原型为:
Python: edges = cv.Canny( image,#input 单通道8-bit灰度图, threshold1,#滞后阈值法中低阈值minVal threshold2,#滞后阈值法中低阈值maxVal [edges],#output边缘图,单通道8位图,与image大小相同 [apertureSize],#孔径尺寸,即Sobel算子的尺寸大小,默认值为3 [L2gradient]#计算梯度幅值L一、L2范数选择,默认False(L2范式 ) )
OpenCV中的Canny算法的码源:略
注意:
一、因为 OpenCV 中 没有执行经典 Canny 方法中的第一步,即省去了滤波平滑;全部咱们须要事前进行平滑处理。
二、OpenCV 中的 Canny 算法仅遍历了一遍图像,就完成了步骤2(梯度计算)和步骤3(非最大值抑制);具体过程是计算当前遍历行的梯度幅值,同时计算前一行的梯度幅角,并完成 3*3 邻域内的非最大值抑制。
三、步骤3(非最大值抑制)和步骤4(滞后阈值处理)是交错在一块儿计算的。
四、步骤4 中的边缘追踪法中,程序是寻找强边缘的 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 车道线检测(实际项目)
略