某天下午的練習...
2010年3月15日 星期一
Arm-removal
在參考互動雙足式機器人之設計與實現這篇論文後,實作了去手臂的模組,目的是避免含有手臂的手會大大降低辨識率。該方法採用逆時針旋轉來統計每個膚色點與重心的距離,如下圖所示:(引用論文圖片)

這種直方圖統計的方式在影像處理課本第十章:表示與描述就看的到。所以,有了這個觀念,剩下的我想怎麼做就怎麼做囉!底下是整個去手臂的流程:

整個流程有幾點補充:

另外,我將去手臂的目標鎖定在下半圓(180~359),也就是預設手不會從上面垂下來,這樣可以避免五指併攏被判斷成手臂的問題。
程式碼下載

這種直方圖統計的方式在影像處理課本第十章:表示與描述就看的到。所以,有了這個觀念,剩下的我想怎麼做就怎麼做囉!底下是整個去手臂的流程:

整個流程有幾點補充:
- Histogram Statistics:水平為角度、垂直為最遠距離。
- Low-pass filter:用 7x7 的遮罩,做二值影像的低通濾波。
- Post-processing:在統計每個膚色點與重心的角度,會因為計算誤差,使相鄰點得到同樣的角度,導致直方圖某些角度沒有值,所以我做了平滑化。
- threshold1、threshold2:前者用來決定是否有手臂存在;後者則是決定去手臂的程度。
- Find valley:這部份需配合下圖作說明,當決定要去手勢時,就開始往兩側找山谷,也就是傾斜度逐漸平緩的點。有時候坡度會緩和一下又繼續往下降,加入 threshold2,目的就是希望找到比較正確的山谷。

另外,我將去手臂的目標鎖定在下半圓(180~359),也就是預設手不會從上面垂下來,這樣可以避免五指併攏被判斷成手臂的問題。
程式碼下載
2010年1月4日 星期一
Motion Detection
「Motion Detection」是第一次接觸電腦視覺時遇到的問題,這個算法試圖從連續影像中找出「移動物體」,處理上可以從相鄰影像、或者以一張背景影像為基礎,而我是採用前者,過程如下:(門檻值設為 20)

接著就是如何從這張二值影像找出物體,這部分可以參考「Digital Image Processing 2/e」一書中的第 11 章:表示與描述,當中提到「Chain Code」與「Polygonal Approximation」,至於我實作的方法是「Connected Component」,非上述兩者...XD。
最後一個要考量的議題是如何取捨這些移動物體,我的作法是傳入一個 function pointer 給 motion detector 物件來使用,這樣一來,就可以自行決定 filter condition,function pointer prototype 如下:
實作範例
程式碼下載
參考資料:

接著就是如何從這張二值影像找出物體,這部分可以參考「Digital Image Processing 2/e」一書中的第 11 章:表示與描述,當中提到「Chain Code」與「Polygonal Approximation」,至於我實作的方法是「Connected Component」,非上述兩者...XD。
最後一個要考量的議題是如何取捨這些移動物體,我的作法是傳入一個 function pointer 給 motion detector 物件來使用,這樣一來,就可以自行決定 filter condition,function pointer prototype 如下:
typedef bool (*filter)(int cond1, int cond2, int threshold1, int threshold2);
實作範例
bool MyFilter(int cond1, int cond2, int threshold1, int threshold2)
{
if(cond1 < (threshold1/16) || cond2 < (threshold2/16)) return true;
else return false;
}
程式碼下載
參考資料:
2009年12月17日 星期四
找出二值影像的邊緣並序列化
標題提到的「序列化」,意思是依序記錄邊緣上的點,以便之後取出該物體的 Fourier Descriptor。找邊緣的演算法很多:canny、snake 等,不過這些我都不會,所以我先用了 sobel 來做,但由於 sobel 會讓物體的邊緣「增厚」,這樣對於我之後的序列化會有困難。所以必須換別的做法。

因為來源是二值影像,所以這邊想到一個更簡潔,效果我覺得一定好的方式 (自我感覺良好:P),整個過程分三步驟:
程式碼下載 (DFS is non-recursive version)

因為來源是二值影像,所以這邊想到一個更簡潔,效果我覺得一定好的方式 (自我感覺良好:P),整個過程分三步驟:
- 對影像做水平掃描,若像素 A 的左或右為背景,則像素 A 為邊緣。
- 對影像做垂直掃描,若像素 A 的上或下為背景,則像素 A 為邊緣。
- 將步驟一得到的水平影像和步驟二的垂直影像做「logical OR operation」。
程式碼下載 (DFS is non-recursive version)
2009年12月16日 星期三
Fourier Descriptor
在「Digital Image Processing 2/e」一書中的第 11 章:表示與描述〈Reprentation and Description〉,裡頭介紹幾種描述物體的方法,例如:鏈碼〈chain code〉、骨架〈skeletonizing〉、邊界描述子〈boundary descriptor〉、紋理〈texture〉等,這些動作其實就是在找物體的特徵,一旦決定了特徵,才能透過辨識引擎去做訓練與辨識。
上述提到的邊界描述子有幾種描述方式,其中一種稱作「Fourier Descriptor」,這裡先做個簡單的介紹。這個方法是透過一維傅立葉轉換,將邊界資料轉換後,取其頻譜〈spectrum〉來當作特徵。有學過影像處理應該都知道,傅立葉轉換的高頻部份用來描述邊緣、細節、甚至是雜訊;低頻則是描述平滑區域、整體形狀。所以在實際應用上,就是把原始的 N 筆邊界資料,轉換後,取其前 M 筆的頻譜值來當特徵〈M <= N〉。
至於該如何量化邊界資料,其實課本說明得很清楚,我們只要把每個點 (x,y) 「視為」x+yi,也就是複數平面上的點,接著,從某點出發,順(或逆)時針依序記錄下來即可。說得更明白一點就是用 Complex[] 陣列紀錄啦!至於將每個點看成一個複數,好處有二(我猜的):
因為這個演算法蠻簡單得,我就自己實作出來,並且驗證課本的正方形範例,不過,要注意一點,由於程式中的座標系和數學上的直角坐標系,Y 座標是上下顛倒,所以需要轉換一下。

程式碼下載
上述提到的邊界描述子有幾種描述方式,其中一種稱作「Fourier Descriptor」,這裡先做個簡單的介紹。這個方法是透過一維傅立葉轉換,將邊界資料轉換後,取其頻譜〈spectrum〉來當作特徵。有學過影像處理應該都知道,傅立葉轉換的高頻部份用來描述邊緣、細節、甚至是雜訊;低頻則是描述平滑區域、整體形狀。所以在實際應用上,就是把原始的 N 筆邊界資料,轉換後,取其前 M 筆的頻譜值來當特徵〈M <= N〉。
至於該如何量化邊界資料,其實課本說明得很清楚,我們只要把每個點 (x,y) 「視為」x+yi,也就是複數平面上的點,接著,從某點出發,順(或逆)時針依序記錄下來即可。說得更明白一點就是用 Complex[] 陣列紀錄啦!至於將每個點看成一個複數,好處有二(我猜的):
- 不改變物體形狀。
- 用一維傅立葉即可。(降維度的味道,因為本來是影像嘛^_^)

因為這個演算法蠻簡單得,我就自己實作出來,並且驗證課本的正方形範例,不過,要注意一點,由於程式中的座標系和數學上的直角坐標系,Y 座標是上下顛倒,所以需要轉換一下。

程式碼下載
訂閱:
文章 (Atom)

