[2011] EDLines: A real-time line segment detector with a false detection control.
以下為本篇文章的閱讀筆記。
這篇文章的綜述部分寫的非常漂亮,有時間一定要翻譯一下。
EDLines的基本結構分為以下三部分:
- 輸入灰度圖,利用 Edge Drawing (ED) 算法進行提取,輸出干凈、連續的像素鏈,又稱為邊緣段 (edge segments)。邊緣段對應於對象邊界;
- 利用最小二乘法從像素鏈中根據直線度准則提取線段;
- 用 Desolneux 等提出的 Helmholtz Principle 來消除線段誤檢。
1. 邊緣檢測 Edge Drawing
ED 算法的優勢:其他邊緣檢測器將二值邊緣圖像作為輸出,且被檢測到的邊緣像素通常是不相關、不連通、不連續的實體,以至於需要更進一步生成潛在的對象邊界。ED算法的輸出為干凈、連續的像素鏈 (同時也是連通的對象邊界),且運行速度較快。
算法流程
給定一個灰度圖,ED 算法執行邊緣檢測進行如下四步輸出邊緣段 (edge segments):
- 首先將圖像經過一個濾波,例如高斯濾波,來抑制圖像噪聲並對圖像進行平滑處理。這里使用的是 \(5\times 5\) 的高斯核,且參數默認值為 \(\sigma = 1\)。
- 計算平滑后圖像每一個像素點的梯度強度和方向。這里可用已知的 Prewitt, Sobel, Scharr 等梯度算子。
- 利用 step 2 得到的平滑圖像計算被稱為錨點 (anchors) 的像素點集合。錨點對應梯度算子產生最大值的像素點,這些像素點也是大概率會成為邊緣部分 (edge elements) 的像素點。
- 對 step 3 中得到的錨點進行連線,從而畫出邊緣。具體過程:從一個錨點出發,ED 利用鄰居像素的梯度強度和方向,通過搜索梯度最大值走向下一個錨點,完成連線。

接下來就是線段提取部分,即,分離這些像素鏈並擬合出直線段。
2. 線段提取
線段提取的基本思想是:依次經過像素格,並用最小二乘線擬合方法擬合出線段,直到誤差超過特定閾值,例如一個像素,並輸出提取線段。然后用算法迭代處理像素鏈上的剩余像素直到所有的像素都擬合完成。
線段提取算法可以被划分為如下幾個階段:
- 第一個
while
循環:用最小二乘生成一個最小長度的初始線段。其中的 最小線段長度依賴於直線有效性參數,將會在直線有效性部分進行解釋; - 第二個
while
循環:通過添加像素延展初始線段。具體做法:檢查像素鏈剩余像素到擬合直線的距離,如果距離小於一定閾值,例如一個像素,就將像素加入到當前線段。直到出現拐點並且線段的方向發生變化; - 輸出當前線段,並對剩余像素進行迭代提取。
LineFit(Pixel *pixelChain, int noPixels){
double lineFitError = INFINITY; // 目前的直線擬合誤差
LineEquation lineEquation; // y = ax + b 或者 x = ay + b
while (noPixels > MIN_LINE_LENGTH){
LeastSquaresLineFit(pixelChain, MIN_LINE_LENGTH, &lineEquation, &lineFitError);
if (lineFitError <= 1.0) break; // OK. 一個初始線段被檢測到。
pixelChain ++; //跳過第一個像素並嘗試剩下的像素
noPixels–; // 少一個像素
} // end-while
if (lineFitError > 1.0) return; //沒有初始線段, Done.
//一個初始線段被檢測到,嘗試延展這個線段。
int lineLen = MIN_LINE_LENGTH;
while (lineLen < noPixels){
double d = ComputePointDistance2Line(lineEquation,
pixelChain[lineLen]);
if (d > 1.0) break;
lineLen++;
} //end-while
// 當前線段結束。計算最后的直線方程並輸出。
LeastSquaresLineFit(pixelChain, lineLen, &lineEquation);
Output ‘‘lineEquation’’
// 從剩余像素中提取線段
LineFit(pixelChain + lineLen, noPixels-lineLen);
} //end-LineFit
3. 直線有效性檢驗
Helmholtz principle: 對於一個有感知意義的結構而言,它偶然出現的期望值(組合或是格式塔)一定是很低的。也即,被檢測到的對象是作為背景模型的外點而存在的。
Number of False Alarms (NFA):根據 Helmholtz principle,直線段的 NFA 定義如下。假設 \(A\) 是一個長度為 \(n\) ,並在尺寸為 \(N \times N\) 像素的圖像中擁有至少 \(k\) 個與之方向對齊的點,那么有
其中 \(N^{4}\) 代表 \(N \times N\) 圖像中潛在線段的個數。概率 \(p\) 代表了直線方向的准確性,它的取值會在參數部分提及。如果一條線段的 NFA 滿足 \(\text{NFA}(n, k) \leqslant \varepsilon\),我們就稱之為具有 \(\varepsilon\) 意義的線段。
基於以上定義,我們給出線段的有效性判定標准:
- 對於長度為 \(n\) 的線段,計算沿着線段的每一個像素的梯度角 (基於未平滑圖像),由此得到方向對齊的像素點數量 \(k\);
- 計算 \(\text{NFA}(n, k)\),當 \(\text{NFA}(n, k) \leqslant 1\) (每張圖像只會出現一次誤檢) 則認為該線段有效,否則認為線段無效。
直線有效性檢驗被是 EDLines 的最后一步,具有可選擇性,如無必要可以省去。直線有效性檢驗往往會過濾掉短線段,而長線段因為與背景有較大偏差,通常都會被保留下來。同時這一步也可以選擇其他快於 Helmholtz principle 的篩選原則以達到更實時提取線段的目的。
4. 內部參數設定
a. 像素點的梯度強度與方向計算;
b. 直線有效性參數:直線上方向對齊像素和准確度 \(p\) 的定義;
c. 梯度閾值、錨點閾值和掃描間隔;
d. 直線擬合參數:最小線段長度、最大均值平方直線擬合誤差。
a. 像素點的梯度強度與方向計算
計算像素點的梯度方向與水平線角度時使用如下公式:
其中 \(I(x, y)\) 為像素點 \((x, y)\) 的強度信息,\(g(x, y)\)為梯度強度,\(\operatorname{angle}(x, y)\) 為水平線角度。為什么要這樣定義? 減少梯度計算的依賴性,盡可能保持像素的不相關的特點,從而在直線有效性檢驗時盡可能滿足 Helmholtz principle。
b. 直線有效性參數:直線上方向對齊像素和准確度 \(p\) 的定義
當兩個點 (或者線段) \(P\) 和 \(Q\) 的角度相差不超過 \(\pi / n\) 時,我們認為 \(P\) 和 \(Q\) 有相同方向, 也即以准確度 \(1 / n\) 對齊。LSD 等文獻表明 \(n\) 不應該超過 8,因此將直線有效性檢驗的准確度 (計算 NFA 時用到) 設置為 \(p = 1/8 = 0.125\),即當點(或線段)滿足角度差小於 \(\pi / 8 = 22.5^{\circ}\) 時我們認為它們具有方向對齊的性質。
c. 梯度閾值、錨點閾值和掃描間隔
- 梯度閾值 \(\rho\)。ED 算法中,在錨點計算與連接步驟中,我們首先需要對梯度至小於閾值 \(\rho\) 的像素進行過濾。
-
錨點閾值 AT。接下來用帶有錨點閾值 ( AT) 的 non-maximal suppression (非極大值抑制) 算法來計算錨點。傳統非極大值抑制算法假設如果某像素梯度值大於等於梯度方向的鄰居像素,那么該像素可以認為是邊緣段的候選點。ED則考慮像素梯度超出梯度方向的鄰居像素某一閾值 (AT) 的像素點作為候選點,這樣能夠提高候選點的質量,得到更為干凈的邊緣段。 沒有錨點閾值最優解的理論基礎,全靠經驗來定。
-
掃描間隔 \(k\)。 掃描間隔定義了算法篩選錨點的稀疏性,\(k = 1\) 則對每行每列的像素篩選錨點,\(k = 4\) 則對每 4 行每 4 列的像素篩選錨點。錨點篩選越稀疏,最后輸出的邊緣地圖的細節就會越少。這里將 \(k\) 設置為 1。
d. 直線擬合參數
-
最小線段長度。 為了使得最短線段能夠通過直線有效性判定,線段長度 \(n\) 需要滿足 \(\text{NFA}(n, n)=N^{4} * p^{n} \leqslant 1\),即 \(n \geqslant \frac{-4 \log (N)}{\log (p)}\),其中 \(p = 0.125\) 。例如在 \(512\times 512\) 的圖像中,最小線段長度為 12 個像素。
-
最大均值平方直線擬合誤差。基於實驗,選取誤差為一個像素。