之前在《在 WIndows 上安裝 Kinect(含 MMD 使用 Kinect 簡易教學)》這篇文章裡,已經大概介紹了一下,怎麼讓 Kinect 這個有趣的 XBox 360 深度攝影機可以在 Windows 上透過 OpenNI 的架構運作了;同時,也大概介紹了一下,怎樣用 Kinect 來讓 Miku Miku Dance 裡的初音跳舞了。
這一篇,則是來介紹一下,怎樣透過 OpenNI,把 Kinect 抓到的人體骨架動作,轉換為一般的鍵盤輸入。這邊用的,是美國 USC(University of Southern California、南加州大學)創新科技研究所(Institute for Creative Technologies、網頁) 的 MxR Lab 所開發的 FAAST(Flexible Action and Articulated Skeleton Toolkit,官方網頁)。
他們最有名的宣傳影片,應該就是用這套 FAAST 來玩《魔獸世界》(WOW、World of Warcraft )了!(參考)
下面就是官方放在 YouTube 的展示影片:
說實話啦,Heresy 自己看完只會覺得:「玩這遊戲還真累啊…」 :p
不過基本上,這雖然只是一般的鍵盤對應,但的確是個滿有趣的應用。
而要怎麼做到一樣的事呢?基本上,第一步驟就是要先以《在 WIndows 上安裝 Kinect(含 MMD 使用 Kinect 簡易教學)》一文中的方式,將 Kinect、OpenNI 以及 NITE 安裝好,並確定可以運作。而接下來,就是到 FAAST 的官方網站,下載 FAAST 的最新版程式(目前是 0.04、直接下載)。下載之後,他會是一個 ZIP 的壓縮檔,解壓縮之後,會有四個檔案:
- FAAST.exe:FAAST 的主程式。
- glut32.dll:OpenGL 的 glut 環境所需要的檔案。
- readme.txt:說明文件。
- Bindings.txt:範例的鍵盤對應檔。
而要使用的話,也很簡單,只要在確定 Kinect 和 OpenNI 可以正常運作的情況下,執行「FAAST.exe」這個程式就可以了。而他跑起來後,也是相當單純的一個視窗,基本上就是下圖的樣子:
在視窗的上方,有一個黑色的框,這邊是會顯示 OpenNI 透過 Kinect 所抓到的資訊。而中間則有三個頁籤:「Sensor」、「Skeletion」、「Actions」可以切換,目前的版本在這裡,「Skeletion」基本上是沒有用的,所以會用到的只有「Sensor」和「Actions」這兩頁。視窗最下方則是有一個文字區域,會顯示所有的訊息,可以當作他是在輸出除錯用的訊息。
而 FAAST 程式執行起來後不會自動連線到 Kinect,要自己去按「Sensor」這個頁籤裡的「Connect」按鈕;如果有正確連接到的話,按鈕會被反白、文字也會變成是「Connected!」,同時上方的黑框也會開始顯示所抓取到的資訊(會類似 NITE 裡的範例 Sample-StickFigure.exe)。
再來,最重要的,就是要設定動作和鍵盤的對應了!目前 FAAST 還只能把動作對應到鍵盤的事件,而沒辦法對應滑鼠或搖桿,這點算是比較可惜的;不過根據官方網頁的說法,他們是會再繼續開發的。
而如果要設定動作和鍵盤的對應,則是要切到「Actions」這一頁(下圖)。
在這邊可以發現,他中間有很大的一塊區域,可以輸入文字,這裡就是用來編輯、顯示動作和鍵盤對應的內容的部分,這也是最重要要調整的區域了!預設開啟 FAAST 應該已經有幾行基本的內容了,可以當作範例來參考。另外,在官網上他們也有提供他們用來操作 WOW 的設定檔,可以讓大家下載回去自己試試看(下載連結)。
而在編輯區域的下方還有三個按鈕,右方的「Load File」和「Save File」是用來讀取和儲存對應設定檔用的;而「Start Input Emulation」就是開啟輸入模擬的功能,當一切就緒後,要按下這個鈕,FAAST 才會真的開始分析動作,進行鍵盤的輸入。
接下來,來看最重要的,也就是鍵盤對應要怎麼寫吧∼他預設的範例內容為:
# format: event_name threshold output_type event
lean_left 20 key a
lean_right 20 key d
lean_forwards 15 key w
lean_backwards 15 key s
 
一開始以「#」開始的兩行都是註解,可以不用管他。而之後的四行,則代表了四種動作,各自對應到四個不同的按鍵;在這裡,他就是把身體向左傾(lean_left)對應成「a」、向右傾(lean_right)對應成「d」、向前傾(lean_forwards)對應成「w」、向後傾(lean_backwards)對應成「s」。
而這邊應該也可以看的出來,實際上這個設定的內容,每行是有四個元素的,他的格式是:
 
他們的意義依序如下:
- action_name代表偵測到的動作名稱,是由 FAAST 定義的;像上面的「lean_left」這類的,就是 FAAST 定義的動作名稱。
- action_threshold代表要這個動作的判定門檻值,單位會因為不同的動作而不同;像在上面的例子裡,因為定義的動作都是傾斜,所以它的單位就是角度,代表傾斜幾度才算數。
- virtual_event_type代表在前面的動作發生的情況下,要送出哪一類的虛擬事件給電腦。在目前的版本,只有一般按鍵的「key」和特殊按鍵的「key_special」兩種。
- virtual_event_name這一項則是在描述前一項「virtual_event_type」的細節。以「key」來說的話,就直接是單一字元了∼而如果是「key_special」的話,則是要搭配十進位的 Virtual-Key Codes。
在動做方面,目前的 FAAST 分為「skeleton」(骨架)和「NITE」兩部分。前者就是透過整個人體骨架的姿勢來做判斷,在目前的版本有 24 個動作;而後者則是 NITE 偵測出來的手勢的部分,目前有七種。下方則是完整的列表:
類型 | 動作名稱 | 意義 | 條件值(單位) |
---|---|---|---|
skeleton | lean_left | 身體左傾 | 身體左傾角度(度) |
lean_right | 身體右傾 | 身體右傾角度(度) | |
lean_forwards | 身體前傾 | 身體前傾角度(度) | |
lean_backwards | 身體後傾 | 身體後傾角度(度) | |
left_arm_forwards | 左手前伸 | 手到肩膀的距離(英寸) | |
left_arm_down | 左手放下 | 手到肩膀的距離(英寸) | |
left_arm_up | 左手舉起 | 手到肩膀的距離(英寸) | |
left_arm_out | 左手向左伸 | 手到肩膀的距離(英寸) | |
left_arm_across | 左手向右伸 | 手交錯過身體到肩膀的距離(英寸) | |
right_arm_forwards | 右手前伸 | 手到肩膀的距離(英寸) | |
right_arm_down | 右手放下 | 手到肩膀的距離(英寸) | |
right_arm_up | 右手舉起 | 手到肩膀的距離(英寸) | |
right_arm_out | 右手向右伸 | 手到肩膀的距離(英寸) | |
right_arm_across | 右手向左伸 | 手交錯過身體到肩膀的距離(英寸) | |
left_foot_forwards | 左腳往前 | 腳到左臀部的距離(英吋) | |
left_foot_sideways | 左腳往左 | 腳到左臀部的距離(英吋) | |
left_foot_backwards | 左腳往後 | 腳到左臀部的距離(英吋) | |
left_foot_up | 左腳舉起 | 左腳離地高度(英吋) | |
right_foot_forwards | 右腳往前 | 腳到右臀部的距離(英吋) | |
right_foot_sideways | 右腳往右 | 腳到右臀部的距離(英吋) | |
right_foot_backwards | 右腳往後 | 腳到右臀部的距離(英吋) | |
right_foot_up | 右腳抬起 | 右腳離地高度(英吋) | |
jump | 跳 | 雙腳離地高度(英寸) | |
walk | 走 | 行走時雙腳離地高度(英寸) | |
NITE | push | 推 | 速度(英吋/秒) |
swipe_up | 往上揮 | 速度(英吋/秒) | |
swipe_down | 往下揮 | 速度(英吋/秒) | |
swipe_left | 往左揮 | 速度(英吋/秒) | |
swipe_right | 往右揮 | 速度(英吋/秒) | |
circle | 畫圓 | 半徑(英寸) | |
wave | 揮手 | 無(請填 0) |
有了這些資料後,又可以把動作對應到按鍵了∼向比如說你希望右手舉高到到 20 英吋,就輸入「a」的話,那就只要加上一行:right_arm_up 20 key a 這樣就可以了∼
另外要注意,如果是要用 skeleton 的動作的話,那要和使用 Sample-StickFigure 或 MMD 時一樣,先進行標準姿勢的校正、識別;也就是在確認 Kinect 有正確地抓到自己的外觀時,擺出標準的校正姿勢(右圖),讓 OpenNI 可以抓到你的骨架。如此一來,他才能根據這些骨架的資料,進行分析。
而如果是要用 NITE 的手勢的話,則是要先做所謂的「focus gesture」,讓系統知道手在哪裡;而所謂的「focus gesture」有兩種,一個是「click」(其實應該算是推,也就把手往前伸再縮回來的動作)、另一個則是「wave」(手舉起左右揮動數次)。詳細的說明,可以參考 NITE 的「NITE Algorithms 1.3」這份文件(位於「C:Program FilesPrime SenseNITEDocumentation」目錄下);不過 Heresy 自己在玩的時候,總覺得手勢的部分,總覺得不是任得很好就是了。
玩了一下後,Heresy 會覺得要寫出一個好的設定會滿麻煩的。因為基本上,有不少的動作其實是有可能同時觸發的。像是「walk」由於就是要抬腳,所以很有可能同時觸發到「foot_up」的事件;同樣的,把手舉起、身體傾斜這類的動作,也很有可能在做其他動作的時候,同時觸發到。而要避免的話,大概得把條件值都設大、讓他只接受大動作了…另外,他的鍵盤事件觸發的狀況,是會去模擬鍵盤的「壓下」和「釋放」兩種事件,和一般鍵盤在壓住時會不停地重複送出鍵盤的事件,其實有點不一樣。
整體來說呢,Heresy 是覺得這類的輸入方法,並不適合用來做常態的輸入,不但累,而且精準度方面也還是有些問題的;也就是說,不要期望真的可以拿來取代鍵盤。而在滑鼠的部分,由於 FAAST 目前還不支援滑鼠的輸入,所以無法用來玩;不然 Heresy 個人會覺得,這類的輸入應該比較適合用來取代滑鼠的。