天天看點

直線hough變換原理及實作

看了一天的hough變換,總算是有些眉目。一開始總是糾結于hough變換把圖像中的點映射到另一個參考系中的直線中,是怎麼實作的。即我怎麼知道圖像中的點事映射到哪些直線中的。。。。。後面終于明白,其做法是将映射到另一個參考系的直線離散化,通過求直線上每個點,來構成直線,進而表達出原圖像此點所在的所有直線。至于最後是選擇映射到極坐标系中是因為減少運算量。本來無邊無際的直線,都可以用有邊有界的模和角度來表示。

Hough 變換是基于點-線的對偶性思想。

在圖像 XY 裡,所有過點(x ,y)的直線的方程為 

                   y = px + q                                (1) 

其中 p 為斜率, q為截距,它也可以改寫成如式(2)的形式: 

                   q = −px+ y                             (2) 

式(2)可以看作為參數空間 PQ 中過點(p ,q)的一條直線。 

如圖下所示,在圖像空間中 XY 中過點(xi  ,  yi)的直線方程可以寫成yi=pxi+q,也可以寫成q=-pxi+yi,後者表示在參數空間PQ中的一條直線。同理對于(xj  ,  yj)也可以寫成上式形式。如下圖:

直線hough變換原理及實作

        由此可知,在圖像空間中共線的點對應在參數空間裡面相交的線,反過來,在參數空間裡面相交于同一個點的所有直線在圖像空間裡面都有共線的點與之對應,這就是點-線的對偶性。

        Hough 變換就是根據這樣的關系把空間裡面的檢測問題轉換到參數空間,通過參數空間裡面進行簡單的累計統計來完成直線的檢測任務。

    在運算式(2)直線方程時候,如果直線接近豎直方向,則會由于p的值都接近無窮而使得計算量增大,此時我們使用直線的極坐标方程來表示直線,如下圖,其方程如式(3) ,

                λ=xcosθ+ysinθ      (3)

直線hough變換原理及實作

根據這個方程,對于任意一組(λ,θ)都對應一條直線。即原來的點-線對偶性變成了現在的點-正弦曲線對偶性,如圖所示,圖(a)表示圖像空間XY 中的5個點,在圖(b)參數空間中對應着5條曲線,這裡的θ為[−90 , +90 ],λ的取值範圍為

直線hough變換原理及實作

, N為圖像的寬度。

直線hough變換原理及實作

     由圖可知,圖像空間中各個點可以看作它們在參數空間裡面的對應曲線。在圖(b)中,曲線 1,3,5 都過 K 點,這表示在圖(a)中點 1,3,5 處于同一條直線上,同理,圖(a)中點 2,3,4 處于同一條直線上,在圖(b)中它們對應的曲線2,3,4 都通過點 L。 

Hough 變換的具體實作步驟如下: 

(1) 建立一個參數(λ,θ) 空間的二維的數組,該數組相當于一個累加器。 

(2) 順序搜尋圖像中所有目标(黑色)像素,對于每一個目标像素,在參數空間中根據式(3)找到對應位置,然後在累加器的對應位置加 1。 

(3) 求出參數空間(累加器)中最大值,其位置為(λ',θ')。 

(4) 通過參數空間位置(λ',θ') ,根據式(3)找到圖像空間中相對應的直線參數。

        對于直線hough變換過程,可以這麼認為。依次周遊圖像的所有像素,對每個像素判斷是否滿足某個特定條件,若滿足,則經過該像素的所有直線區域的計數器加1。為了得到經過某個像素的所有直線區域,可以依次用θ的所有可能取值(例如θ可以以1度為增量,從-90度取到+90度),根據(3)式求出λ的值,進而得到很多組(λ,θ),就對應了所有經過此像素的直線。

下面是實作方式:

為避免hough變換程式中多次計算三角函數值,可以采用先用數組存儲每個可能的三角函數值,再用查找表的方法查找對應三角函數值,進而提高效率。示例如下:

double sin_value[180];
double cos_value[180];
for(int i=-90; i<90; i++)
{
    sin_value[i+90] = sin(i*3.1415926/180);
    cos_value[i+90] = cos(i*3.1415926/180);
}
           

Hough變換的主要流程如下:

for(y=0; y<h; y++)  //h為圖像和寬度
{
    for(x=0; x<w; x++)  //w為圖像寬度
    {
        //對θ的所有取值進行計算
        for(i=0; i<180; i++)
        {
            tp = (int)(x*sin_value[i] + y*cos_value[i]);
            hough_acc[tp][i] += 1;
        }
    }
}
           

上面隻是簡單的計算流程,在實際應用中,可以根據像素點的灰階值、像素點的範圍等來判斷是否計算目前點對應的所有(λ,θ)

繼續閱讀