2013年2月28日 星期四

EmguCV Image Process: Extracting Lines, Contours, and Components part 2

轉戰新時代廣場
EmguCV Image Process: Extracting Lines, Contours, and Components

參考OpenCV 2 Computer Vision Application Programming Cookbook第七章

介紹內容如下:

Detecting image contours with the Canny operator

Detecting lines in images with the Hough transform

Fitting a line to a set of points

Extracting the components' contours

Computing components' shape descriptors

上一篇介紹了Canny algorithm來偵測線段

這次來介紹透過Canny algorithm的影像

利用Hough Transform(霍夫轉換)來線段偵測

一條直線在二維空間上,可以透過兩種坐標系來表示

一種是:笛卡兒坐標系

另一種是:極座標系

笛卡兒坐標系,透過斜率和截距來表示

而極坐標系,則透過極角 Ɵ 和極徑 r 來表示

如下圖:

(此圖出自http://www.opencv.org.cn)

而Hough Transform就是透過這種極坐標系的方式來表示直線

此直線的方程式:

(此圖出自http://www.opencv.org.cn)

因此在作直線偵測的時候

需要帶入兩個參數:Ɵ(theta)跟r(eho)


而在OpenCV中提供了兩種Hough Transform的線段偵測

HoughLines和HoughLinesP

前者為標準的Hough Transform

後者為統計的Hough Transform

HoughLines所偵測出來的是"直線"

意即所偵測出來的線是沒有端點的!!
(就是一條直線)

而HoughLinesP所偵測出來的是"線段"

意味著偵測出來的線是有端點的!!


而本篇要討論的是EmguCV直接在Image的類別中提供的方法 HoughLines

雖然名稱與OpenCV提供的標準Hough Transform相同

但卻是實作統計的Hough Transform

但又與OpenCV中使用HoughLinesP的方式不太一樣

在OpenCV中無論你要使用哪一個Hough Transform的方法

都必須先經過Canny Algorithm計算

把得到的二值化影像當作參數傳入Hough Transform的方法中

而在EmguCV中則直接把HoughLines與Canny Algorithm整合起來

因此在HoughLines的方法裡

需要帶入Canny Algorithm的參數


直接來看看程式吧:

Image<Gray, Byte> image = new Image<Gray, Byte>("image.jpg");
//Hough transform for line detection
LineSegment2D[][] lines = image.HoughLines(
    new Gray(125),  //Canny algorithm low threshold
    new Gray(260),  //Canny algorithm high threshold
    1,              //rho parameter
    Math.PI/180.0,  //theta parameter 
    100,            //threshold
    50,             //min length for a line
    50);            //max allowed gap along the line
//draw lines on image
foreach (var line in lines[0])
{
    image.Draw(line, new Gray(255), 1);
}
可以發現在HoughLines這個方法的引數裏頭

第一個和第二個參數就是上一篇提到的Canny algorithm所需的參數

而第三個參數:rho parameter則表示極坐標中極徑r的最小單位

在這邊就是設定為1(像素)

而第四個參數:theta parameter則表示極坐標中極角Ɵ的最小單位

在這邊就是設定為為PI/180,也就是1(度角)

第五個參數表示線段偵測的閥值,越低就會偵測到越多線段
(這在文章後面再做詳細的討論)

第六個參數:就是只要偵測的線段長度必須大於此設定

避免偵測到過短的線段

第七個參數:在EmguCV的文件說明中是這樣解釋:

Minimum gap between lines

不知道是不是我的英文太爛

這樣的解釋意思應該是:線與線之間的最短間距

也就是"線段與線段間的距離,應該要大於此設定"吧!

但這樣的解釋是有誤的

在這個參數所代表的意義,應該是:

max allowed gap along the line
(此原文出自:OpenCV 2 Computer Vision Application Programming Cookbook)

中文的意思是:一條線段之間的最大間距

什麼意思呢??

在Hough transform中所偵測出來的線段,可能會是斷裂的

也就是說,同一條線段,可能因為影像成像、參數設定等原因

被偵測成好幾段的線段

但這幾條線段其實應該是同一條

但程式如何判別這幾條線段是屬於同一條呢??

就是依據此參數

若是某兩條線段是屬於同一條直線上

並且之間的間距小於所設定的值

就認為這兩條線段是同一條線段!


接著在用foreach迴圈把線段畫在影像上

結果如下:

結果可以發現,大部分的線段都有偵測出來,但多了一些奇怪的線

如果將參數做一些調整

LineSegment2D[][] lines = image.HoughLines(
    new Gray(125),  //Canny algorithm low threshold
    new Gray(260),  //Canny algorithm high threshold
    1,              //rho parameter
    Math.PI/180.0,  //theta parameter 
    130,            //threshold
    100,             //min length for a line
    30);            //max allowed gap along the line

結果如下:
這時就是看如何找到最適當的參數去做調整


那這裡來解釋一下到底Hough transform的threshold是如何計算??

前面一開始有先提到直線方程式

(此圖出自http://www.opencv.org.cn)

如果今天繪製一張座標影像

縱軸是極徑rho、橫軸是極角theta

在這樣的坐標系中,一個點就代表著一條直線

假設這裡要計算出x-y坐標系上,通過某一點(50, 30)的所有直線

並利用上述的直線方程式,將所有直線繪製到剛剛所說的座標影像上

//Create Hough accumulator
Image<Gray, byte> HoughImage = new Image<Gray, byte>(180,180);
//Choose a point
int x = 50, y = 30;
//Loop over all angles
for (int i = 0; i < 180; i++)
{
    double theta = i * Math.PI / 180.0;
    //Find corresponding rho value
    double rho = x * Math.Cos(theta) + y * Math.Sin(theta);
    //j corresponds to rho from -100 to 100
    int j = (int)(rho + 100.5);
    //Draw white point on HoughImage
    HoughImage[j, i] = new Gray(255);
}

上面的程式,就是計算極角介於0~180度,通過x-y坐標系(50, 30)這個點的所有直線

繪製出來的影像如下:

這條曲線上的每一個點,代表著通過x-y坐標系(50, 30)這個點的直線

如果這裡再加上一個x-y坐標系(30, 10)這個點呢?

會發現這兩條曲線有一個交會點

那這個交會點,代表著什麼意思呢??

這個交會點,代表著通過x-y坐標系上(50, 30)、(30, 10)這兩個點的直線!!

那這跟Hough transform的threshold有什麼關係??

Hough transform就是利用所有二值化影像上的點

去找出所有通過的直線 (繪製出所有曲線)

其中會找到非常多的交會點

這些交會點就代表著一條條的直線

那什麼樣的直線具有意義??

這條直線需要通過多少個二值化影像上的點呢??

這就是threshold這個參數的意義

多少條曲線交會而成的點,才符合偵測條件的直線!!


多做一些參數上的調整來試試看

就能夠更加的了解這些參數所代表的意義了!!


關於OpneCV Hough transform的介紹,這裡提供了很棒的說明!!

下一篇介紹用Hough Transform來做圓的偵測!!

沒有留言:

張貼留言