遇到的影像類型大概是這兩種:
1.影像中的極值本身很接近、平緩區域多,通常發生在物體離攝影機靠得很近的狀況,例如手指偵測(通常手指不能離攝影機太遠,會偵測不到),stackoverflow上面這類問題最多人點讚的一篇做狗的手掌指點的大概也是這問題。
畫成波形圖大概是這種感覺,其中紅色星號是要找的地方
這種近距離的影像找極值會遇到的困難點是什麼,第一、有些地方是平緩的、有些地方不是端點卻有微微凸起,用一階微分來找正負號變換處的話平緩的地方會變消掉、微凸的地方會被標到。當然還有些模擬退火法之類的,但是我在2d的狀況遇到了點問題。
所以後來我就用opencv裡的floodfill做了很簡單的事,先掃過一遍找山頂,用floodfill把山挖掉,接下來就能找下一座山頭了。floodfill中有參數可以調整pixel值最多上升多少或下降多少,善用這功能可以一座一座山挖掉。
假設今天有這樣一隻手
先找到極值
然後用floodfill向下填滿
找下一個極值
再挖掉
再找下一個
再挖掉
最後剩一個
找了極值、挖掉
大概是這樣,有點慢,但是沒啥好方法的話可以考慮。
2.影像中極值距離遠、每個極值之間大小有一定差距、通常出現在目標物較遠的影像中。
畫成圖大概像這樣:
這種問題就比較像一般local maxium會討論的問題,在影像上通常目標物夠大,不用很精準的抓到一個特定的點也是能輸出的很好。用一階微分(如laplace filter或canny filter)效果通常不會太差,但是要抓到tip點有時候會有問題。最近在網路上看到一個Local Binary Patterns的方法還行,最近在嘗試。
做法大概是這樣:
1.先選一個點,比較外圍一圈的pixel值,如果大於中間一定的threshold則填1
所以一個圓形的feature可能是000000或1111111,大多數都是0100101這種,我們選擇只有一端開口或沒有開口的0000000、1111111、0111111、0011111這種,開口數可以比較0轉換成1和1轉換成0的次數(記得尾端要跟第一個數字比),像0110111就是4、0010111也是4,我們選擇2跟0。然後再限制一下開口的0的次數,例如7/4這樣。
最後就會如下圖,紅色是找到的地方,黑色是沒找到的地方,大致上可以把身體濾掉。
詳細的論文請看An adaptive local binary pattern for 3D hand tracking這篇論文
沒有留言:
張貼留言