在边缘检测算法里面Sobel是比较简单的一个算法,但是其检测出来的边缘往往是比较粗的,效果不是很好,因为我们最理想的边缘肯定就是一个宽度为1的细线。
Canny算法在此基础上进行了改进,通过使用边缘的梯度信息进行非最大值抑制(NMS)和利用双阈值,这些措施消除了假性边缘,提高了边缘检测的效果。
Canny边缘检测分为以下几个部分:
高斯滤波
Sobel边缘检测
非最大值抑制
双阈值边缘检测
弱边缘连接
高斯滤波和Sobel边缘检测在之前的文章里面介绍过,在这里不再赘述。
可以参见:FPGA图像处理--Sobel边缘检测FPGA图像处理--高斯模糊(一)FPGA图像处理--高斯模糊(二)这三篇文章。
在本篇中为大家介绍Canny边缘检测中的NMS部分。
我们通过Sobel的计算可以获得两个信息,分别是梯度的幅值和方向。
梯度的幅值可以表示为:
因为我们想在FPGA中实现Canny算子,而根号对FPGA来说消耗的资源是比较多的,因此我们选择另一种幅值的表示方式:
梯度的方向可以表示为:
接下来就可以通过梯度的幅值和方向来做NMS了。
我们在做完Sobel之后得到的幅值和方向也就是下面一幅示意图
每一个点都有其方向和梯度的值。
假如我们Sobel检测的阈值设置的为90,那么在上面示意图中左上角的99,108,110,97这几个点都会被看做边缘部分,在Canny中会对这个做NMS,首先看到99他的梯度方向向下,然后梯度方向下一个值是110比99大,那么就认为99这个点不是边缘,110比他更靠近边缘部分,这样99就被抑制掉了,边缘也能够被细化。对于108来说,他的梯度方向下一个值是77,比108小,那么108就不会被抑制。通过这种方式就能完成非最大值抑制。
在上图里面展示的梯度方向只有0,45,90这些角度,然而在实际计算中不可能只有这些角度的,所以我们要进行插值计算,接下来就说明一下如何进行插值计算。
以任意一点为坐标原点,如上图中的5这个点,他周围有一个3*3的矩阵,然后他的梯度方向是红色箭头的方向。这个方向不在X和Y轴的45°方向(PS:我们规定图像向下为Y轴正方向,向右为X轴正方向,象限为顺时针方向)。
因为其不在45°方向,那么就不能直接将5的梯度和1,9的梯度进行比较来确定是否对5这点进行抑制,那么我们就需要使用插值的方式来生成两个点(亚像素点)进而进行判断。
在上图里面可以看到GX和GY的方向相同并且GX大于GY,所以我们分别选取6 9和1 4这四个点来进行插值以生成两个亚像素点。
在之前的介绍里面我们知道梯度的方向是用arctan来表示的,但是这个计算比较复杂,我们也仅仅是为了插值计算,所以并不需要进行arctan的计算,只需要拿到GX和GY的值即可。
因为GX大于GY,所以让GY/GX这样得到一个小于1的值,记作weight。那么我们就可以得到一个比例关系:
point1 = 9*weight +6 *(1 - weight)
point2 = 1*weight+4* (1 - weight)
这样就能得到两个亚元素点,通过比较5这个点和point1以及point2的大小就可以决定是否对其进行抑制。
通过将GX和GY的关系可以分为以下四种情况:
|GX| >|GY| 并且 GX和GY同号
|GX|>|GY|并且 GX和GY异号
|GX| < |GY| 并且 GX和GY同号
|GX| < |GY| 并且 GX和GY异号
其他几个方向的分析就不赘述了,可以直接看代码里面的实现:
代码里面矩阵的坐标关系如下图:
python实现的参考模型如下:
可以根据上面的坐标对应关系来分析剩下的几种情况。
来看一下实现的效果:
可以明显看到nms之后的结果相对于sobel之后的结果要细化很多。
Python的NMS参考模型介绍完了,之后就是Verilog的RTL怎么实现它,今天就写到这里,休息。
-
FPGA
+关注
关注
1625文章
21663浏览量
601670 -
图像处理
+关注
关注
27文章
1280浏览量
56627 -
边缘检测
+关注
关注
0文章
92浏览量
18201
原文标题:FPGA图像处理--Canny边缘检测(一)
文章出处:【微信号:FPGA开源工坊,微信公众号:FPGA开源工坊】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论