在邊緣檢測算法里面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
+關注
關注
1626文章
21678瀏覽量
602022 -
圖像處理
+關注
關注
27文章
1282瀏覽量
56657 -
邊緣檢測
+關注
關注
0文章
92瀏覽量
18202
原文標題:FPGA圖像處理--Canny邊緣檢測(一)
文章出處:【微信號:FPGA開源工坊,微信公眾號:FPGA開源工坊】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論