PrimeSense 的 NiTE 主要是提供了人的骨架追蹤,以及手部追蹤的功能,基本上應該算是在 OpenNI 這個架構下,最重要、也最常被使用的 middleware library 了。不過由於他的手部追蹤的功能,僅能提供位置的追蹤、和簡單的動態手勢辨識,並沒有辦法去針對手的狀態、或是手指作分析,算是比較可惜的地方。
而現在,PrimeSense 又推出了一套新的 middleware library:Grab Detector,可以用來檢查使用者的手是否有做出抓(grab)的動作了!他的網址是:http://www.openni.org/files/grab-detector/,目前有提供 Windows 版的 32 / 64 位元程式,讓開發者可以使用了~
目前的版本下載後,會是一個「Demo.zip」的壓縮檔,在解開後,裡面會有一個「GrabDetector.pdf」的說明文件,解釋他的「grab」手勢、以及基本使用的概念;而函式庫本身,則是放在「Redistributable」這個目錄,「Demo」目錄底下,就是官方提供的範例程式。比較可惜的是,它可以用來參考的文件並不多,所以應該是得看著 API 和範例來摸索了。
根據文件的說法,這個函式庫和 NiTE 只需要深度影像不同,Grab Detector 同時需要深度影像與彩色影像,並且設定位置校正、以及同步後,才能正常運作(參考)。比較適當的操作距離,是建議在 2-2.5M 之間,同時,由於也需要彩色影像,所以室內不要太暗,會有比較好的效果。
所以,如果是沒有彩色影像的 ASUS Xtion Pro,基本上就不能用了。而如果是使用 Kinect 感應器的話,由於 OpenNI 2 官方的模組並不支援影像位置校正的功能,所以必須要去使用修改過的 Kinect.dll 才行(參考)。
不過實際上,如果進去看他的 API 的話,可以發現,實際上 Grab Detector 在只有深度影像的情況下,還是可以運作的!不過效果會變比較差就是了。
如果是想測試他的效果的話,可以執行「\Demo\Win32\Release」目錄下的「GrabViewer.exe」這個程式(或是也可以執行 64 位元的版本);他執行起來後的畫面,大致上會如下圖:
基本上,由於他是先使用 NiTE 的 Hand Tracker 來做手的追蹤,然後再透過 Grab Detector 來做分析,所以一開始要使用「Click」(手往前推出再收回)或「Wave」(揮手)、來完成手的定位。
而接下來,他就會開始針對手的姿勢來做分析、偵測 grab 這個手勢了~而 Grab Detector 定義的「grab」的手勢,基本上如下面的圖片:
他基本上是定義把五隻手指靠攏為「grab」、用來做偵測。而他也有特別提到,建議不要用握拳的形式來做,雖然可能也會成功,但是效果會比較差。而如果要釋放的話,基本上就是把手張開就好了。
如果手勢變化的事件有成功地偵測到的話,應該會看到畫面上手上的「RELEASE」會變成「GRAB」的字樣,而另外一個命令提示字元視窗,也會有對應的文字出現。
在 Heresy 這邊自己測試的話,感覺效果算是還不錯了~
而如果想知道程式該怎麼寫的話,則是可以參考「Demo\Samples\GrabViewer」底下的專案。
實際上真的要寫的話,它必要的檔案都放在「Redistributable」這個目錄下,「Common」裡面的兩個 header 檔,就是要使用時所需要的 header 檔;而「data」目錄裡面則是在執行階段需要的資料檔案。Windows 平台上所需要的 lib 和 dll 檔,則分別在 Win32 和 x64 這兩個資料夾內,可以根據自己建置的程式平台來使用。
要使用 Grab Detector 的話,大致上會是這樣的流程:
-
include GrabDetector.h 這個檔案,然後所需要的物件會在 PSLabs 這個 namespace 下。
-
按照一般的流程,建立 OpenNI NiTE 的程式,包括了初始化 OpenNI 環境、建立需要的 VideoStream 並完成相關設定,以及初始化 NiTE 環境、建立出 HandTracker、並完成設定。
-
透過 PSLabs::CreateGrabDetector() 建立出 PSLabs::IGrabDetector 的物件,來做後續的操作。
在建立時,要指定要使用的 Device、以及所需要的資料檔(Redistributable\Common\Data\grab_gesture.dat)所在的路徑。 -
透過 PSLabs::IGrabDetector 的 AddListener() 函式,來設定當事件觸發時,要做什麼事。
-
這邊基本上是要繼承 PSLabs::IGrabEventListener 來寫一個新的類別,並在這個類別裡面實作 ProcessGrabEvent() 這個函式,針對不同的事件,作個別的處理。
他接到的資料會是 PSLabs::IGrabEventListener::EventParams,透過他的 Type 變數,可以知道現在的事件是什麼;這包括了 GRAB_EVENT、RELEASE_EVENT 以及 NO_EVENT 三種可能。
-
-
接下來,進入主迴圈後,則是每次透過 PSLabs::IGrabDetector 提供的 SetHandPosition() 來設定目前手的位置(可由 HandTracker 取得),並透過 UpdateFrame() 來提供新的深度、彩色畫面。
-
這邊是說需要 VGA 解析度(640 x 480)的影像。
-
雖然文件是說要有彩色、深度影像,不過實際上僅有深度影像也可以使用,但是效果會較差。
-
-
程式結束後,透過 PSLabs::ReleaseGrabDetector() 來釋放掉 PSLabs::IGrabDetector 這個物件。
而如果不想使用 Listener/callback 的形式來使用 Grab Detector 的話,也可以在主迴圈內,透過 PSLabs::IGrabDetector 的 GetLastEvent() 來取得最後一個事件,藉此來做處理。
不過另外要注意的是,這個函式庫從界面來看,應該只能針對一只手作偵測而已,還不確定要怎麼針對兩隻(或以上)的手做偵測;或許之後有空再來研究看看吧?
這篇大致上就先這樣了,Heresy 自己有成功地寫出一個簡單的程式、可以成功地偵測到手勢的變化,所以應該是可以用沒問題的。完整的範例,就晚一點再放出來吧~
另外,其實如果純以 OpenNI 的深度圖,搭配 OpenCV,其實也可以針對手部做一些分析(參考),真的要的話,應該也可以做到一定的程度地辨別?或許之後試試看能不能拿這個方法,來便是手是否是張開的吧~
heresy大大,运行不了啊,分析不出问题。openni2_GrabDetector.obj : error LNK2019: 无法解析的外部符号 _ReleaseGrabDetector@4,该符号在函数 _main 中被引用
1>openni2_GrabDetector.obj : error LNK2019: 无法解析的外部符号 _CreateGrabDetectorFromHandle@8,该符号在函数 “class PSLabs::IGrabDetector * __stdcall PSLabs::CreateGrabDetector(class openni::Device &,char const *)” (?CreateGrabDetector@PSLabs@@YGPAVIGrabDetector@1@AAVDevice@openni@@PBD@Z) 中被引用
1>C:Documents and Settingslcmy documentsvisual studio 2010Projectsopenni2_GrabDetectorDebugopenni2_GrabDetector.exe : fatal error LNK1120: 2 个无法解析的外部命令
1>
to chao
請確認專案在編譯時、編譯器有正確連結到正確的 GrabDetector.lib 這個檔案。
heresy大大有木有放出自己的范例?求下载学习
to pozhenzi
本站之前已經有發表過簡單的範例教學了
http://viml.nchc.org.tw/blog/paper_info.php?CLASS_ID=1&SUB_ID=1&PAPER_ID=462