Canny算子计算流程:

高斯滤波和Sobel算子已经在前面讲过,所以这里主要讨论非最大值抑制和滞后分割电路设计。

非最大值一直电路设计

非最大值抑制主要是对Sobel运算的计算结果进行开窗,在当前像素的3x3邻域找到梯度方向上的最大值,若当前像素为整个方向上的最大值,则将该像素点归为潜在的边缘点。否则,直接置为非边缘点。

基于FPGA的Canny算子设计(一)_java

我们首先要明白当前像素的梯度值位于哪一个象限,假定其位于第一象限,则有

基于FPGA的Canny算子设计(一)_java_02

假定该点计算结果为result,则有

基于FPGA的Canny算子设计(一)_java_03

不妨再列出第二象限的计算公式

设计的难点在于梯度方向上两个潜在极大值的插值运算f算子。有两点值得我们注意:

1) f算子中包含除法,这是在FPGA中不容易处理的。

2) 前两个象限的除法运算的分子和分母是颠倒的,这是不容易设计的。

所以就需要进行算法的等效转换,首先想到的就是将除法转换为乘法运算,这个是比较容易实现的,以第一象限公式为例,两边同时乘以x,则有

基于FPGA的Canny算子设计(一)_java_04

基于FPGA的Canny算子设计(一)_java_05

对于第二象限,两边同时乘以y,则有

基于FPGA的Canny算子设计(一)_java_06

基于FPGA的Canny算子设计(一)_java_04

不等式右边第一项系数为当前xy方向梯度值的较小值,第二项系数为当前xy方向梯度的较大值与较小值之差,不等式左边系数为当前xy方向梯度值的较大值。因此,将公式变换如下:

基于FPGA的Canny算子设计(一)_java_08

基于FPGA的Canny算子设计(一)_java_09

上式中,Mmax代表当前xy方向梯度值的较大值,Mmin代表当前xy方向梯度值的较小值。C0C1C2C3,则分别代表4个插值元素。对于8个不同的象限,插值元素的索引号如下表所示:


Index of C0

Index of C1

Index of C2

Index of C3

15象限

2

5

6

3

26象限

2

1

6

7

37象限

0

1

8

7

48象限

0

3

8

5

这样,就可以实现4个主象限的计算一致性,同时将转换为FPGA所擅长的乘法和加法运算。

在查表得到插值元素时,需要知道当前的象限信息,得到象限信息的最简单办法就是通过查询xy方向梯度值的符号。同时,需要得到两个值的比较关系。需要注意的是,我们需要Sobel运算结果的xy方向的输出,以及模值输出,实际上并不需要方向计算。

第一阶段的计算电路如图所示:

基于FPGA的Canny算子设计(一)_java_10

首先将Sobelxy方向的计算结果通过Cordic模块输出两个值的绝对值的较大值Max和较小值Min,以及输入坐标的象限信息Quadrant_info。接着为了得到当前像素的8个插值元素,即当前窗口,我们需要将上面三个数据及Sobel的模值结果Mudule送入win_buf得到窗口缓存。我们需要的是当前窗口的9个元素Mudule(8:0),以及上面三个数据的当前值Max(4)Min(4)Quadrant_info(4)

第二阶段的计算电路如图所示:

基于FPGA的Canny算子设计(一)_java_11

第二阶段的计算将象限信息和当前窗口像素送入查找表,由查找表电路得到C0C1C2C3输出。然后在此基础上做f算子,得到的结果与中心窗口值与Max的乘积进行比较。最后,在比较的结果上进行分割。