當前位置:首頁 > 嵌入式 > 嵌入式硬件

像點擊(clicks)是GUI平臺的核心,輕點(taps)是觸摸平臺的核心那樣,手勢(gestures)是Kinect應用程序的核心。和圖形用戶界面中的數(shù)字交互不同,手勢是現(xiàn)實生活中存在的動作。如果沒有電腦我們就不需要鼠標,但是沒了Kinect,手勢依然存在。從另一方面講,手勢是日常生活中人與人之間相互交流的一部分。手勢能夠增強演講的說服力,能夠用來強調(diào)和傳遞情感。像揮手(waving)或者指點(pointing)這些手勢都是某種無聲的演講。

Kinect應用程序的設(shè)計和開發(fā)者的任務就是將這些現(xiàn)實生活中存在的手勢映射到計算機交互中去以傳達人的想法。嘗試從鼠標或觸摸式的GUI設(shè)計移植基于手勢的自然交互界面要做很多工作。借鑒過去30多年來對于這一概念的研究,以及從一些Kinect for Xbox的體感游戲中獲取一些設(shè)計理念,計算機工程師和交互設(shè)計師一起為Kinect創(chuàng)建了一系列新的手勢庫。

本文將會介紹用戶體驗的一些知識,并討論如何將手勢應用到Kinect應用程序中。我們將展示Kinect如何作為自然交互界面(Natural User Interface)的人機交互模型的一部分。我們將討論一些具體的使用Kinect來進行手勢識別及交互的例子。更重要的是,將會展示一些已經(jīng)作為Kinect手勢識別庫中的手勢。

1. 什么是手勢

在許多不同的學科中,手勢(gesture)有著其獨特的含義,可能這些含義之間有某些異同。在藝術(shù)領(lǐng)域,手勢被用來傳達舞蹈中最富表現(xiàn)力的部分,特別是在亞洲舞蹈藝術(shù)中,手勢被作為某些宗教符號或者象征。在交互設(shè)計領(lǐng)域,在基于觸摸的自然交互界面中手勢和操控有很大區(qū)別。

以上這些說明手勢在不同的學科領(lǐng)域都有自己獨特的含義。在學術(shù)領(lǐng)域都試圖對手勢定義一個抽象的概念。在用戶體驗設(shè)計領(lǐng)域使用最廣泛的關(guān)于手勢的定義實在Eric Hulteen 和Gord Kurtenbach 1990年發(fā)表的一篇名為人機交互中的手勢(Gestures in Human-Computer Communication),定義如下:”手勢是身體的運動,他包含一些信息。揮手道別是一種手勢。敲擊鍵盤不是手勢,因為用手指的運動去敲擊按鍵沒有被觀察,也不重要,他只表達的鍵盤被按下這一動作。(A gesture is a motion of the body that contains information. Waving goodbye is a gesture. Pressing a key on a keyboard is not a gesture because the motion of a finger on its way to hitting a key is neither observed nor significant. All that matters is which key was pressed)”

這個定義既解釋了什么是手勢也解釋了什么不是手勢。像這樣的下一個正式的定義通常有兩個方面的困難,既要避免太具體也要避免太抽象。如果一個定義太具體-如,定義某項技術(shù)-可能會隨著UI技術(shù)的變化會變得模糊不清。作為一種學術(shù)定義而不是以常見的用法為基礎(chǔ)的定義,它也必須足夠一般,并且符合或者說廣大的研究機構(gòu)先前已發(fā)表在HCI的研究成果及藝術(shù)中符號學。另一方面,定義過于寬泛,也會有有無關(guān)緊要的風險:如果一切都是一種姿態(tài),那么就什么都不是了。

Eric Hulteen 和Gord Kurtenbach關(guān)于手勢的定義的中心在于手勢能夠用來交流,手勢的意義在于講述而不是執(zhí)行。

有趣的是將語言和行為引入到人機交互接口中來,這是一種徹底的變革。我們與計算機交互語音變?yōu)闊o聲的語言(mute):我們通過指點和手勢而不是語言與計算設(shè)備進行溝通。當和計算機進行交互時,我們點擊鍵盤按鍵或觸摸屏幕。我們似乎更喜歡這種形式的靜音通信即使當前的技術(shù)能夠支持更簡單的語音指令。我們沒有操作(manipulation)的力量,和虛擬的對象而不是真實的物體進行交互,因而沒有持久性。運動成為純粹的手勢。

基于Eric Hulteen 和Gord Kurtenbach的定義,我們都明白什么是 UI 操作 ——暫時不是一種手勢 ——理解什么是手勢以及手勢表示"重大"行為或者符號仍然有很大的困難。移動交互的含義是什么?手勢進行溝通和語言進行溝通的最明顯不同是什么?我們做手勢的象征意義往往很抽象簡單。

在人機交互領(lǐng)域,手勢通常被作為傳達一些簡單的指令而不是交流某些事實、描述問題或者陳述想法。使用手勢操作電腦通常是命令式的,這通常不是人們使用手勢的目的。例如,揮手(wave)這一動作,在現(xiàn)實世界中通常是打招呼的一種方式,但是這種打招呼的方式在人機交互中卻不太常用。通常第一次寫程序通常會顯示“hello”,但我們對和電腦打招呼并不感興趣。

但是,在一個繁忙的餐館,揮手這一手勢可能就有不同的含義了。當向服務員招收時,可能是要引起服務員注意,需要他們提供服務。在計算機中,要引起計算機注意有時候也有其特殊意義,比如,計算機休眠時,一般都會敲擊鍵盤或者移動鼠標來喚醒,以提醒計算機“注意”。當使用Kinect時,可以使用更加直觀的方式,就行少數(shù)派報告阿湯哥那樣,抬起雙手,或者簡單的朝計算機揮揮手,計算機就會從休眠狀態(tài)喚醒。

在人機交互領(lǐng)域,手勢通常有一些含義,表示有意讓某些事情發(fā)生。手勢是一種指令。當通過鼠標或者觸控板去點擊UI界面上的按鈕時,我們希望按鈕會觸發(fā)其背后的事件。通常,按鈕上會有一個標簽來指示按鈕的功能如:開始、取消、打開、關(guān)閉。我們的手勢操作就是想要實現(xiàn)這些事件。

上面的定義中的第一點可以得出,手勢的另一個特點是比較隨意(arbitrary)。手勢有限定的領(lǐng)域,那么在該領(lǐng)域之外沒有任何意義。令人驚訝的是除了指向(pointing)和聳肩(shurg),人類學家沒有發(fā)現(xiàn)任何東西我們可以稱之為一種通用的手勢。然而,在計算機的UI中,指向(pointing)通常被認為是直接操作因為它牽涉到跟蹤,同時聳肩的含義太微妙而不好辨識。因此,我們想要使用的任何Kinect手勢必須基于應用程序的用戶 和應用程序的設(shè)計和開發(fā)者之間就某種手勢代表的含義達成一致。

因為手勢是任意的(arbitrary)所以他們也是基于約定的(conventional)。應用程序的設(shè)計者必須告訴用戶正在使用的手勢的意義,或者是這些手勢是約定俗稱大家都知道的。此外,這些約定不是基于語言文化,而是對已確定的技術(shù)規(guī)則。我們知道如何使用鼠標 (行為學習) 并不是因為這是我們已經(jīng)從我們的文化導入的東西,而是因為這是基于特定的圖形用戶界面的跨文化約定。同樣地,我們知道如何點擊或滑動智能手機,不是因為這些都是文化的約定,而是因為這些都是跨文化自然用戶界面項約定。有趣的是,我們在一定程度上知道如何點擊平板電腦,因為我們以前學習了如何使用鼠標單擊。技術(shù)約定之間可以相互轉(zhuǎn)化,這是因為語言和手勢可以通過不同的語言和文化之間來轉(zhuǎn)換。

然而,手勢的這種任意性和基于約定的特性也帶來了誤解性(misunderstanding),這是在設(shè)計任何用戶界面,尤其是像Kinect這樣的沒有任何預先設(shè)定好的操作約定的用戶界面時需要關(guān)注的風險。就像在有些國家,點頭表示否定搖頭表示可能。手勢,或者任何身體的運動,都有可能產(chǎn)生誤解。

總之,在人機交互領(lǐng)域,手勢是:

表達一種簡單的命令天生有隨意性基于某種協(xié)定可能被誤解

注意:實際的直接操作(manipulation)不是手勢。

2. 自然交互界面(NUI)

討論手勢而不討論自然用戶界面顯然不完整。自然用戶界面是一系列技術(shù)的合計,他包括:語音識別,多點觸控以及類似Kinect的動感交互界面,他和Windows和Macs操作系統(tǒng)中鼠標和鍵盤交互這種很常見圖形交互界面不同。就像圖像交互界面和之前的命名行交互界面不同那樣。

自然交互界面自然在哪兒呢?早期自然交互界面的發(fā)起者認為交互界面的設(shè)計應該對用戶非常直觀,使用用戶先天就會的行為來進行交互操作。他的目標是不需要操作由圖標和菜單構(gòu)成的基于GUI 的應用程序界面,因為這種界面通常具有陡峭的學習曲線。相反,理想化的狀態(tài)是,用戶應該能夠走到應用程序前面,就能夠開始使用它。在過去的幾年里隨著觸摸功能的智能手機和平板電腦的流行,逐漸取代了鍵盤鼠標,當我們看到孩子們開始走到任何觸摸屏設(shè)備面前,用手去觸摸它,期待它的響應,在這一點上看這一理念已經(jīng)實現(xiàn)。

雖然自然用戶界面的自然性似乎是直接操作的最佳寫照,當使用手指來進行觸摸交互時,先天自然和后天學習行為之間的對立被打破。一些手勢,如輕觸屏幕,在某種意義上就是先天就會的動作。其他的動作比如說雙擊,獲得點擊然后拖拉等,沒有先天就會。而且隨著不同的設(shè)備制造商開始支持不同觸摸手勢,為了使得相同的手勢在不同的觸摸平臺上有相同的意義和行為,為某些手勢定義一些約定顯得更加重要。

自然用戶界面(NUI)的自然性更多的是一種相對自然的概念。對于NUI的更現(xiàn)代的理解受Bill Buxton所影響。他認為NUI界面的設(shè)計充分利用了用戶預先就會的技能,用戶和UI進行交互感到很自然,使得他們甚至忘了是從哪里學到這些和UI進行交互所需的技能的。換句話說,第一次操作時,我們不記得我們曾經(jīng)學過這些知識。例如,輕點(tap)這個手勢早平板電腦和手機中使用的很頻繁,這個技能是從我們之前在傳統(tǒng)的人機交互界面上使用鼠標來指向并點擊某一個界面上的元素學來的。點擊(click)和輕點(tap)的最主要區(qū)別在于,點擊需要鼠標,對于觸摸屏,不需要額外的設(shè)備,只需要用手指輕輕觸摸一下屏幕就可以了。

這引出了自然用戶界面的另一個特點。用戶和計算機之間的交互看起來不需要任何媒介,這種相互作用的媒介是不可見的。例如,在語音識別界面中,人機交互是通過具有復雜電子過濾去噪的麥克風實現(xiàn)的,其內(nèi)部有解析發(fā)音語義單元的各種算法,將這些語義傳遞給其它軟件來進行將特定的短語解釋為命令,并將該命令映射到某種軟件功能操作。但是,內(nèi)部的這一切,對用戶是不可見的。當用戶對計算機發(fā)出這樣的命令,"嘿,注意我",她會認為計算機會像類似大多數(shù)人的本能那樣的響應這個命令。

自然用戶界面的 依賴于先驗知識和不需要媒介的交互這兩個特征是每一種NUI界面的共同特征,其他方面如觸摸,語音和動態(tài)交互界面則因設(shè)備的不同而各異。目前,大多數(shù)關(guān)于NUI的設(shè)計都是基于多點觸控體驗的。這就是為什么前面對于手勢的標準定義是那樣定義的。它是將多點觸摸的場景進行修改并將手勢和操作區(qū)分開來。

關(guān)于手勢(gesture)和操作(manipulation)的爭論也存在于語音交互界面中,命令等同于手勢,語音等同于直接操作,在動態(tài)交互界面中,將手或者身體追蹤展示在可視化界面上手和身體的運動等同于直接操作。自由形式的運動像揮手這一動作就屬于手勢。

但是Kinect還有第三種交互界面,他和觸摸和語音交互不同。那就上一篇文章中所講的姿勢(pose),姿勢是身體的某一部分和其他部分之間的一種靜態(tài)關(guān)系,他不是運動的。Kinect中的姿勢和日常生活中的姿勢是一樣的,例如,左臂伸出45度表示將當前的窗口變?yōu)榛顒拥慕换ゴ绑w,右臂伸出45度或者135度表示垂直滾動工具欄。

另外,交互方式可以從一種類型的交互界面轉(zhuǎn)換到另外一種交互界面。以按鈕為例,按鈕其實就是一個符號,這是一個先驗的圖形用戶界面。從最基本的功能來講,按鈕就是一個通過鼠標點擊在一個可視化元素的文字或者圖像上觸發(fā)一些命令的工具。在過去15年,按鈕被作為人機交互界面的一個集成部分,被轉(zhuǎn)換到多點觸摸界面,以及Kinect用戶界面中來。

自然用戶界面設(shè)計師所追求的是的是自然,按鈕恰好提供了這一點。但是按鈕在每一種用戶界面中的轉(zhuǎn)換都面臨著一些挑戰(zhàn)。

圖形用戶界面中按鈕的一個通常的特征是他提供了一個懸浮狀態(tài)來指示用戶光標已經(jīng)懸停在的按鈕上方的正確位置。這種懸浮狀態(tài)將點(click)這個動作離散開來。懸浮狀態(tài)可以為按鈕提供一些額外的信息。當將按鈕移植到觸摸屏交互界面時,按鈕不能提供懸浮狀態(tài)。觸摸屏界面只能響應觸摸。因此,和電腦上的圖像用戶界面相比,按鈕只能提供“擊”(click)操作,而沒有“點”(point)的能力。

當將按鈕移植到基于Kinect的用戶界面上時,按鈕的行為就變得更加特殊了?;贙inect的圖形界面中,按鈕的行為和觸摸界面中的剛好相反,他只提供了懸浮(hover)的“點”(point)的能力,沒有“擊”(click)的能力。按鈕這種更令用戶體驗設(shè)計者感到沮喪的弱點,在過去的幾年里,迫使設(shè)計者不斷的對Kinect界面上的按鈕進行改進,以提供更多巧妙的方式來點擊視覺元素。這些改進包括:懸停在按鈕上一段時間、將手掌向外推(笨拙地模仿點擊一個按鈕的行為)等。

雖然觸摸界面也有手勢,但Kinect 界面有些互動不是手勢,不過軟件的開發(fā)和設(shè)計者傾向于以 Kinect 手勢操作作為交互界面。這似乎是因為使用手勢作為物理操作是 Kinect 應用程序的最大的特點。與此相反的是,觸摸界面的突出特點是直接操作。雖然可能不準確,人們通常將自然交互界面劃分為三類:語音交互界面,觸摸交互界面和手勢交互界面。

然而,在關(guān)于Kinect的相關(guān)介紹文檔中,你會發(fā)現(xiàn)有時候姿勢(pose)和操作(manipulation)都被描述為手勢。這些都沒有錯。要記住的是,當我們討論Kinect中的一些術(shù)語,如揮手(wave),滑動(swipe),我們會作為純粹的手勢,而姿勢和操控只有在隱喻意義上才稱之為手勢。

以上的討論都很重要,因為我們會進一步設(shè)計Kinect互動的語意,我們將最終移除從其他圖形界面上借鑒過來的關(guān)于按鈕的語意,然后嘗試建立基于Kinect的先驗的語意。揮手(wave)這是Kinect中純粹的手勢,是最早的這種嘗試。喬治亞技術(shù)研究所的研究人員正在利用 Kinect 來解釋美國手語。相反,其他研究人員,正在利用 Kinect 解釋身體語言——另一種預先形成的手勢和姿勢的溝通。諸如此類的研究可以視為對于NUI的第二層研究。這些逐漸接近了最初NUI人機交互的原始的夢想,不只是看不見,而且NUI能夠自適應以理解我們的行為,而不是迫使我們了解我們和電腦的人機交互。

3. 手勢從哪里來

在手勢交互界面中,純粹的手勢,姿勢和追蹤以及他們之間的組合構(gòu)成了交互的基本術(shù)語。對于Kinect來說,目前可以使用的有8個通用的手勢:揮手(wave),懸浮按鈕(hover button),磁吸按鈕(magnet button),推按鈕(push button),磁吸幻燈片(magnetic slide),通用暫停(universal pause),垂直滾動條(vertical scrolling)和滑動(swipping)。其中的一些術(shù)語是微軟自己引入的,有一些是游戲代理商設(shè)計的,還有一些是Kinect for PC開發(fā)人員為了開發(fā)應用而引入的。

很少情況下會為人際交互界面術(shù)語進行定制。通常要將這8種手勢區(qū)分開來,并在一些應用中通用也不常見。相似的情況在web術(shù)語和手機手勢中設(shè)計新的界面時也會遇到,其中只有部分的設(shè)計能夠變成標準。在網(wǎng)頁設(shè)計領(lǐng)域,走馬燈和光標動畫流行一時,并在一片鄙夷聲中迅速消失。在手機設(shè)計領(lǐng)域由于蘋果公司在觸摸屏領(lǐng)域的早期地位這種術(shù)語得到了很好的規(guī)范。蘋果引入了一些觸摸手勢術(shù)語,如輕點(tap),點住不放(tap and hold),滑動swipe及pinch。

image

交互術(shù)語形成規(guī)范有幾個障礙。第一個就是為了獲得利益而避免標準化。在90年代后期的瀏覽器大戰(zhàn)中,盡管各大廠商在口頭上說標準化協(xié)議很重要,但是在瀏覽器開發(fā)上依舊不停的開發(fā)自己的HTML版本,以吸引開發(fā)者使用他們的技術(shù)。設(shè)備制造商可以利用市場占有率的優(yōu)勢來鎖定消費者,通過在他們的手機上實現(xiàn)自己定義語意的觸屏,來推行自己的手勢操作。這些都是不自然的行為,因為不同廠商對于同一手勢的語意都不同,并且他們看起來不自然,使用不同廠商的產(chǎn)品需要再學習。

另一種形成規(guī)范化的障礙是上下文手勢的專利。例如,蘋果公司不能對“滑動”(swipe)操作申請專利,但是它可以對“滑動解鎖手機”這個手勢申請專利,這使得其他公司需要使用這一技術(shù)或者設(shè)計理念時要么給蘋果公司支付專利費,要么將蘋果告上法庭以避免專利費,或則干脆不使用這一上下文手勢。如果不使用這一上下文手勢,那么產(chǎn)品就破壞了之前我們學習到使用很自然的方式滑動解鎖手機,音樂播放器,平板電腦等這一約定了。

最后一個障礙是,設(shè)計一個手勢很困難。手勢術(shù)語會面對一些App Store中手機應用程序和YouTube中視頻應用所遇到的一些問題:人們要么會要么不會。手勢需要思考如何定義的簡單使得人們能夠去用,這就是長尾理論留下來的問題。

那么什么樣的手勢術(shù)語才是好的呢。如果一個手勢易于使用,那么他就被認為是設(shè)計良好的。在交互設(shè)計中,易用性有兩個方面:可用(affordance)和反饋(feedback)。反饋就是說用戶知道當前正在進行的操作。在網(wǎng)頁中,點擊按鈕會看到按鈕有一點偏移,這就表示交互成功。鼠標按鍵按下時的聲音在某種意義上也是一種反饋,他表示鼠標在工作。對于Winodw Phone Metro風格的界面上的磁貼,開發(fā)這認為這些按鈕應該足夠大,以容下大面積的觸摸區(qū)域,但是他們也認為過大的觸摸區(qū)域會使得用戶觸摸到區(qū)域外面也會觸發(fā)注冊的事件。另外,狀態(tài)信息或者確認對話框會在應用程序中彈出以提示用戶發(fā)生了一些事情。在 Xbox 的儀表板中,使用Kinect傳感器產(chǎn)生的光標懸停在的熱點上開始動畫播放。

如果說反饋發(fā)生在操作進行中或者之后,那么可用性(affordance)就發(fā)生在操作之前了??捎眯跃褪且环N提示或者引導,告訴用戶某一個可視化元素是可以交互的,指示用戶該元素的用處。在GUI交互界面中,按鈕是能夠最好的完成這些理念的元素。按鈕通過文字或者圖標提示來執(zhí)行一些函數(shù)操作。GUI界面上的按鈕通過懸浮狀態(tài)可以提示用戶其用途。最好的可用性-可能有點繞圈-就是約定俗成。用戶知道某一個可視化元素的用途,因為之前在其他應用中使用過類似的可視化控件,或者是在其他設(shè)備中執(zhí)行過類似的操作。但是,這一點對于基于Kinect的手勢交互界面來說有點困難,因為一切都是新的。

通常的做法就是使用借用其他類型交互界面中的約定。在觸摸交互界面中,一個輕點(tap)手勢和通常的鼠標點擊是等同的。響應輕點事件的兩個可視化元素,圖標和按鈕,也被設(shè)計的和傳統(tǒng)的GUI界面上的圖標和按鈕一樣,來達到提示用戶該元素的作用這一目的。Kinect也使用按鈕和圖標來使得用戶能夠更加容易使用。因為Kinect基本上是基于”點”(pointing)而原生不支持“擊”(clicking)。在此之前,軟件界面設(shè)計者和開發(fā)者的花費了很多精力來對手勢交互界面進行定制以實現(xiàn)“擊”這一動作。

和觸摸交互界面不一樣,手勢交互界面可以從社會中人的一般手勢中借用一些手勢操作。這就使得揮手(wave)成為Kinect應用程序的經(jīng)典手勢。因為這一姿勢和現(xiàn)實生活中的姿勢有象征性聯(lián)系使得非常容易理解和使用。軌跡追蹤,雖然在技術(shù)上不是手勢,但是他是另一個在現(xiàn)實生活中和指點有聯(lián)系的術(shù)語。當在電視機或者顯示器前揮動手時,好的Kinect應用程序應該能夠追蹤到手的運動,并顯示一個光標隨著手一起運動。當我們在現(xiàn)實生活中指點物體時,Kinect中的手部追蹤顯示的手形圖標的反饋使得程序更加易用。

目前,現(xiàn)實生活中的易用性手勢在Kinect交互界面中用的比較少,大部分的易用性都是從傳統(tǒng)的GUI界面上的可用性移植過來的。隨著時間的改變,這一點會得到改善。在觸摸屏設(shè)備上新的手勢通過在傳統(tǒng)的已經(jīng)建立的約定中添加手指來形成。兩指輕點和一指輕點有些不同,使用兩個手指或者多個手指進行滑動有其獨特的含義。最終,觸摸手勢全部由手指完成。另一方面,真正的手勢用戶界面,有一個近乎無限的語意庫,使得我們可以基于現(xiàn)實生活中相關(guān)聯(lián)的手勢進行改進。

本文接下來從理論到實現(xiàn),討論如何實現(xiàn)手勢識別,并展示了Kinect中八中基本手勢中的揮手(wave)手勢的識別。

4. 實現(xiàn)手勢識別

Microsoft Kinect SDK并沒有包含手勢識別引擎。因此需要開發(fā)者來定義和手勢識別。從SDK的Beta版放出以來,一些第三方開發(fā)者創(chuàng)建的手勢引擎已初見端倪。但是,微軟沒有將他們作為標準的引擎??磥磉@可能還要等微軟將手勢識別引擎添加到SDK中來,或者指明可替代的解決方案。本節(jié)對手勢識別技術(shù)進行了簡單介紹,希望能夠幫助開發(fā)者在標準的手勢識別引擎出來之前,可以自己動手開發(fā)手勢識別引擎。

手勢識別相對來說可以簡單也可以很復雜,這取決與要識別的手勢。有三種基本的方法可以用來識別手勢:基于算法,基于神經(jīng)網(wǎng)絡和基于手勢樣本庫。每一種方法都有其優(yōu)缺點。開發(fā)者具體采用那種方法取決與待識別的手勢、項目需求,開發(fā)時間以及開發(fā)水平?;谒惴ǖ氖謩葑R別相對簡單容易實現(xiàn),基于神經(jīng)網(wǎng)絡和手勢樣本庫則有些復雜。

4.1 基于算法的手勢識別

算法是解決軟件開發(fā)中幾乎所有問題的最基本方法。使用算法的基本流程就是定義處理規(guī)則和條件,這些處理規(guī)則和條件必須符合處理結(jié)果的要求。在手勢識別中,這種算法的結(jié)果要求是一個二值型對象,某一手勢要么符合預定的手勢要么不符合。使用算法來識別手勢是最基本的方法,因為對于有一點編程能力的開發(fā)這來說,手勢識別的代碼易于理解,編寫,維護和調(diào)試。

但是,最簡單直接的方法也有其缺點。算法的簡單性限制了其能識別到的手勢的類別。對于揮手(wave)識別較好的算法不能夠識別扔(throw)和擺(swing)動作。前者動作相對簡單和規(guī)整,后者則更加細微且多變??赡苣軌?qū)懸粋€識別擺動(swing)的算法,但是代碼可能比較費解和脆弱。

算法還有一個內(nèi)在的擴展性問題。雖然一些代碼可以重用,但是每一種手勢必須使用定制的算法來進行識別。隨著新的手勢識別算法加入類庫,類庫的大小會迅速增加。這就對程序的性能產(chǎn)生影響,因為需要使用很多算法來對某一個手勢進行識別以判斷該手勢的類型。

最后,每一個手勢識別算法需要不同的參數(shù),例如時間間隔和閾值。尤其是在依據(jù)流程識別特定的手勢的時候這一點顯得尤其明顯。開發(fā)者需要不斷測試和實驗以為每一種算法確定合適的參數(shù)值。這本身是一個有挑戰(zhàn)也很乏味的工作。然而每一種手勢的識別有著自己特殊的問題。

4.2 基于神經(jīng)網(wǎng)絡的手勢識別

當用戶在做手勢時,手勢的形式并不總是足夠清晰到能夠判斷用戶的意圖。例如跳躍手勢,跳躍手勢就是用戶短暫的跳起來,腳離開地面。這個定義不能夠提供足夠的信息來識別這一動作。

咋一看,這個動作似乎足夠簡單,使得可以使用算法來進行識別。首先,考慮到有很多種不同形式的跳躍:基本跳躍(basic jumping)、 跨欄(hurdling)、 跳遠(long jumping)、 跳躍(hopping),等等。但是這里有一個大的問題就是,由于受到Kinect視場區(qū)域的限制,不可能總是能夠探測到地板的位置,這使得腳部何時離開地板很難確定。想象一下,用戶在膝蓋到下蹲點處彎下,然后跳起來。手勢識別引擎應該認為這是一個手勢還是多個手勢:下蹲或 下蹲跳起或者是跳起?如果用戶在蹲下的時間和跳躍的時間相比過長,那么這一手勢可能應被識別為下蹲而不是跳躍。

看到這些,最開始對跳躍的定義就會變得模糊。這一姿勢很難定義清楚,使得不能夠通過定義一些算法來進行識別,同時這些算法由于需要定義過多的規(guī)則和條件而變得難以管理和不穩(wěn)定。使用對或錯的二值策略來識別用戶手勢的算法太簡單和不夠健壯,不能夠很好的識別出類似跳躍,下蹲等動作。

神經(jīng)網(wǎng)絡的組織和判斷是基于統(tǒng)計和概率的,因此使得像識別手勢這些過程變得容易控制?;谑裁淳W(wǎng)絡的手勢識別引擎對于下蹲然后跳躍動作,80%的概率判斷為跳躍,10%會判定為下蹲。

除了能夠識別復雜和精細的手勢,神經(jīng)網(wǎng)絡方法還能解決基于算法手勢識別存在的擴展性問題。神經(jīng)網(wǎng)絡包含很多神經(jīng)元,每一個神經(jīng)元是一個好的算法,能夠用來判斷手勢的細微部分的運動。在神經(jīng)網(wǎng)絡中,許多手勢可以共享神經(jīng)元。但是每一中手勢識別有著獨特的神經(jīng)元的組合。而且,神經(jīng)元具有高效的數(shù)據(jù)結(jié)構(gòu)來處理信息。這使得在識別手勢時具有很高的效率。

使用基于神經(jīng)網(wǎng)絡進行手勢識別的缺點是方法本身復雜。雖然神經(jīng)網(wǎng)絡以及在計算機科學中對其的應用已經(jīng)有了好幾十年,建立一個好的神經(jīng)網(wǎng)絡對于大多數(shù)程序員來說還是有一些困難的。大多數(shù)開發(fā)者可能對數(shù)據(jù)結(jié)構(gòu)中的圖和樹比較熟悉,而對神經(jīng)網(wǎng)絡中尺度和模糊邏輯的實現(xiàn)可能一點都不了解。這種缺乏建立神經(jīng)網(wǎng)絡的經(jīng)驗是一個巨大的困難,即使能夠成功的構(gòu)建一個神經(jīng)網(wǎng)絡,程序的調(diào)試相當困難。

和基于算法的方法相比,神經(jīng)網(wǎng)絡依賴大量的參數(shù)來能得到精確的結(jié)果。參數(shù)的個數(shù)隨著神經(jīng)元的個數(shù)增長。每一個神經(jīng)元可以用來識別多個手勢,每一個神經(jīng)遠的參數(shù)的變化都會影響其他節(jié)點的識別結(jié)果。配置和調(diào)整這些參數(shù)是一項藝術(shù),需要經(jīng)驗,并沒有特定的規(guī)則可循。然而,當神經(jīng)網(wǎng)絡配對機器學習過程中手動調(diào)整參數(shù),隨著時間的推移,系統(tǒng)的識別精度會隨之提高。

4.3 基于樣本的識別

基于樣本或者基于模版的手勢識別系統(tǒng)能夠?qū)⑷说氖謩莺鸵阎氖謩菹嗥ヅ?。用戶的手勢在模板庫中已?jīng)規(guī)范化了,使得能夠用來計算手勢的匹配精度。有兩種樣本識別方法,一種是存儲一系列的點,另一種方法是使用類似的Kinect SDK中的骨骼追蹤系統(tǒng)。在后面的那個方法中,系統(tǒng)中包含一系列骨骼數(shù)據(jù)和景深幀數(shù)據(jù),能夠使用統(tǒng)計方法對產(chǎn)生的影像幀數(shù)據(jù)進行匹配以識別出已知的幀數(shù)據(jù)來。

這種手勢識別方法高度依賴于機器學習。識別引擎會記錄,處理,和重用當前幀數(shù)據(jù),所以隨著時間的推移,手勢識別精度會逐步提高。系統(tǒng)能夠更好的識別出你想要表達的具體手勢。這種方法能夠比較容易的識別出新的手勢,而且較其他兩種方法能夠更好的處理比較復雜的手勢。但是建立這樣一個系統(tǒng)也不容易。首先,系統(tǒng)依賴于大量的樣本數(shù)據(jù)。數(shù)據(jù)越多,識別精度越高。所以系統(tǒng)需要大量的存儲資源和CPU時間的來進行查找和匹配。其次系統(tǒng)需要不同高度,不同胖瘦,不同穿著(穿著會影響景深數(shù)據(jù)提取身體輪廓)的樣本來進行某一個手勢。

5.識別常見的手勢

選擇手勢識別的方法通常是依賴于項目的需要。如果項目只需要識別幾個簡單的手勢,那么使用基于算法或者基于神經(jīng)網(wǎng)絡的手勢識別就足夠了。對于其他類型的項目,如果有興趣的話可以投入時間來建立可復用的手勢識別引擎,或者使用一些人家已經(jīng)寫好的識別算法,接下來本文介紹幾種常用的手勢,并演示如何使用算法的方法來識別他們,手勢識別的另外兩種方法由于其復雜性本文不做介紹。

不論選擇哪種手勢識別的方法,都必須考慮手勢的變化范圍。系統(tǒng)必須具有靈活性,并允許某一個手勢有某個范圍內(nèi)的變動。很少有人能夠每次都做一模一樣的手勢。例如,考慮周伯通當前左右手畫圓圈這個手勢,重復這一手勢10次,圓形的中心每次都在一個點嗎,圓形的起點和重點每次都在相同的地方嗎?每次畫圓的時長都一樣嗎?然后使用右手做這個動作,最后比較結(jié)果?;蛘呃瓗讉€朋友或者家人來做,然后觀察。也可以站在鏡子前面看自己做,或者使用錄像設(shè)備錄下來再看。技巧就是對于某一手勢,讓盡可能多的人來做,然后試圖標準化這一手勢。手勢識別一個比較好的方式就是關(guān)注手勢最核心的部分而不是哪些外在的細枝末節(jié)。

5.1 揮動(wave)手勢

只要玩過Xbox上的體感游戲,可能都使用過揮手這個手勢。揮手這一手勢不論年齡大小都能夠做的一個簡單動作。這是一個友好的,快樂的手勢,人們通常揮手或者招手來打招呼或者道別。在應用開發(fā)的上下文中,揮手手勢通常告訴應用程序已經(jīng)準備好了,可以開始體驗應用了。

揮手是最簡單最基本的手勢。使用算法方法能夠很容易識別這一手勢,但是之前講到的任何方法也能夠使用。雖然揮手是一個很簡單的手勢,但是如何使用代碼來識別這一手勢呢?讀者可以在鏡子前做向自己揮手,然后仔細觀察手的運動,尤其注意觀察手和胳膊之間的關(guān)系。繼續(xù)觀察手和胳膊之間的關(guān)系,然后觀察在做這個手勢事身體的整個姿勢。有些人保持身體和胳膊的不動,使用手腕左右移動來揮手。有些人保持身體和胳膊不動使用手腕前后移動來揮手。可以通過觀察這些姿勢來了解其他各種不同揮手的方式。

XBOX中的揮手動作定義為:從胳膊開始到肘部彎曲。用戶以胳膊肘為焦點來回移動前臂,移動平面和肩部在一個平面上,并且胳膊和地面保持平行,在手勢的中部(下圖1),前臂垂直于后臂和地面。下圖展示了這一姿勢。

image

從圖中可以觀察得出一些規(guī)律,第一個規(guī)律就是,手和手腕都是在肘部和肩部之上的,這也是大多是揮手動作的特征。這也是我們識別揮手這一手勢的第一個標準。

第一幅圖展示了揮手這一姿勢的中間位置,前臂和后臂垂直。如果用戶手臂改變了這種關(guān)系,前臂在垂直線左邊或者右邊,我們則認為這是該手勢的一個片段。對于揮手這一姿勢,每一個姿勢片段必須來回重復多次,否則就不是一個完整的手勢。這一運動規(guī)律就是我們的第二個準則:當某一手勢是揮手時,手或者手腕,必須在中間姿勢的左右來回重復特定的次數(shù)。使用這兩點通過觀察得到的規(guī)律,我們可以通過算法建立算法準則,來識別揮動手勢了。

算法通過計算手離開中間姿勢區(qū)域的次數(shù)。中間區(qū)域是一個以胳膊肘為原點并給予一定閾值的區(qū)域。算法也需要用戶在一定的時間段內(nèi)完成這個手勢,否則識別就會失敗。這里定義的揮動手勢識別算法只是一個單獨的算法,不包含在一個多層的手勢識別系統(tǒng)內(nèi)。算法維護自身的狀態(tài),并在識別完成時以事件形式告知用戶識別結(jié)果。揮動識別監(jiān)視多個用戶以及兩雙手的揮動手勢。識別算法計算新產(chǎn)生的每一幀骨骼數(shù)據(jù),因此必須記錄這些識別的狀態(tài)。

下面的代碼展示了記錄手勢識別狀態(tài)的兩個枚舉和一個結(jié)構(gòu)。第一個名為WavePosition的枚舉用來定義手在揮手這一動作中的不同位置。手勢識別類使用WaveGestureState枚舉來追蹤每一個用戶的手的狀態(tài)。WaveGestureTracker結(jié)構(gòu)用來保存手勢識別中所需要的數(shù)據(jù)。他有一個Reset方法,當用戶的手達不到揮手這一手勢的基本動作條件時,比如當手在胳膊肘以下時,可調(diào)用Reset方法來重置手勢識別中所用到的數(shù)據(jù)。

private enum WavePosition{    None = 0,    Left = 1,    Right = 2,    Neutral = 3}private enum WaveGestureState{    None = 0,    Success = 1,    Failure = 2,    InProgress = 3}private struct WaveGestureTracker{    public int IterationCount;    public WaveGestureState State;    public long Timestamp;    public WavePosition StartPosition;    public WavePosition CurrentPosition;    public void Reset()    {        IterationCount = 0;        State = WaveGestureState.None;        Timestamp = 0;        StartPosition = WavePosition.None;        CurrentPosition = WavePosition.None;    }}

下面代碼顯示了手勢識別類的最基本結(jié)構(gòu):它定義了五個常量:中間區(qū)域閾值,手勢動作持續(xù)時間,手勢離開中間區(qū)域左右移動次數(shù),以及左手和右手標識常量。這些常量應該作為配置文件的配置項存儲,在這里為了簡便,所以以常量聲明。WaveGestureTracker數(shù)組保存每一個可能的游戲者的雙手的手勢的識別結(jié)果。當揮手這一手勢探測到了之后,觸發(fā)GestureDetected事件。

當主程序接收到一個新的數(shù)據(jù)幀時,就調(diào)用WaveGesture的Update方法。該方法循環(huán)遍歷每一個用戶的骨骼數(shù)據(jù)幀,然后調(diào)用TrackWave方法對左右手進行揮手姿勢識別。當骨骼數(shù)據(jù)不在追蹤狀態(tài)時,重置手勢識別狀態(tài)。

public class WaveGesture{    private const float WAVE_THRESHOLD = 0.1f;    private const int WAVE_MOVEMENT_TIMEOUT = 5000;    private const int LEFT_HAND = 0;    private const int RIGHT_HAND = 1;    private const int REQUIRED_ITERATIONS = 4;    private WaveGestureTracker[,] _PlayerWaveTracker = new WaveGestureTracker[6, 2];    public event EventHandler GestureDetected;    public void Update(Skeleton[] skeletons, long frameTimestamp)    {        if (skeletons != null)        {            Skeleton skeleton;            for (int i = 0; i < skeletons.Length; i++)            {                skeleton = skeletons[i];                if (skeleton.TrackingState != SkeletonTrackingState.NotTracked)                {                    TrackWave(skeleton, true, ref this._PlayerWaveTracker[i, LEFT_HAND], frameTimestamp);                    TrackWave(skeleton, false, ref this._PlayerWaveTracker[i, RIGHT_HAND], frameTimestamp);                }                else                {                    this._PlayerWaveTracker[i, LEFT_HAND].Reset();                    this._PlayerWaveTracker[i, RIGHT_HAND].Reset();                }            }        }    }}

下面的代碼是揮手姿勢識別的主要邏輯方法TrackWave的主體部分。它驗證我們先前定義的構(gòu)成揮手姿勢的條件,并更新手勢識別的狀態(tài)。方法識別左手或者右手的手勢,第一個條件是驗證,手和肘關(guān)節(jié)點是否處于追蹤狀態(tài)。如果這兩個關(guān)節(jié)點信息不可用,則重置追蹤狀態(tài),否則進行下一步的驗證。

如果姿勢持續(xù)時間超過閾值且還沒有進入到下一步驟,在姿勢追蹤超時,重置追蹤數(shù)據(jù)。下一個驗證手部關(guān)節(jié)點是否在肘關(guān)節(jié)點之上。如果不是,則根據(jù)當前的追蹤狀態(tài),揮手姿勢識別失敗或者重置識別條件。如果手部關(guān)節(jié)點在Y軸上且高于肘部關(guān)節(jié)點,方法繼續(xù)判斷手在Y軸上相對于肘關(guān)節(jié)的位置。調(diào)用UpdatePosition方法并傳入合適的手關(guān)節(jié)點所處的位置。更新手關(guān)節(jié)點位置之后,最后判斷定義的重復次數(shù)是否滿足,如果滿足這些條件,揮手這一手勢識別成功,觸發(fā)GetstureDetected事件。

private void TrackWave(Skeleton skeleton, bool isLeft, ref WaveGestureTracker tracker, long timestamp){    JointType handJointId = (isLeft) ? JointType.HandLeft : JointType.HandRight;    JointType elbowJointId = (isLeft) ? JointType.ElbowLeft : JointType.ElbowRight;    Joint hand = skeleton.Joints[handJointId];    Joint elbow = skeleton.Joints[elbowJointId];    if (hand.TrackingState != JointTrackingState.NotTracked && elbow.TrackingState != JointTrackingState.NotTracked)    {        if (tracker.State == WaveGestureState.InProgress && tracker.Timestamp + WAVE_MOVEMENT_TIMEOUT < timestamp)        {            tracker.UpdateState(WaveGestureState.Failure, timestamp);            System.Diagnostics.Debug.WriteLine("Fail!");        }        else if (hand.Position.Y > elbow.Position.Y)        {            //使用 (0, 0) 作為屏幕的中心.  從用戶的視角看, X軸左負右正.            if (hand.Position.X <= elbow.Position.X - WAVE_THRESHOLD)            {                tracker.UpdatePosition(WavePosition.Left, timestamp);            }            else if (hand.Position.X >= elbow.Position.X + WAVE_THRESHOLD)            {                tracker.UpdatePosition(WavePosition.Right, timestamp);            }            else            {                tracker.UpdatePosition(WavePosition.Neutral, timestamp);            }            if (tracker.State != WaveGestureState.Success && tracker.IterationCount == REQUIRED_ITERATIONS)            {                tracker.UpdateState(WaveGestureState.Success, timestamp);                System.Diagnostics.Debug.WriteLine("Success!");                if (GestureDetected != null)                {                    GestureDetected(this, new EventArgs());                }            }        }        else        {            if (tracker.State == WaveGestureState.InProgress)            {                tracker.UpdateState(WaveGestureState.Failure, timestamp);                System.Diagnostics.Debug.WriteLine("Fail!");            }            else            {                tracker.Reset();            }        }    }    else    {        tracker.Reset();    }}

下面的代碼添加到WaveGestureTracker結(jié)構(gòu)中:這些幫助方法維護結(jié)構(gòu)中的字段,使得TrackWave方法易讀。唯一需要注意的是UpdatePosition方法。TrackWave調(diào)用該方法判斷手的位置已經(jīng)移動。他的最主要目的是更新CurrentPosition和Timestamp屬性,該方法也負責更新InterationCount字段合InPorgress狀態(tài)。

public void UpdateState(WaveGestureState state, long timestamp){    State = state;    Timestamp = timestamp;}public void Reset(){    IterationCount = 0;    State = WaveGestureState.None;    Timestamp = 0;    StartPosition = WavePosition.None;    CurrentPosition = WavePosition.None;}public void UpdatePosition(WavePosition position, long timestamp){    if (CurrentPosition != position)    {        if (position == WavePosition.Left || position == WavePosition.Right)        {            if (State != WaveGestureState.InProgress)            {                State = WaveGestureState.InProgress;                IterationCount = 0;                StartPosition = position;            }            IterationCount++;        }        CurrentPosition = position;        Timestamp = timestamp;    }}

上述代碼片段就可以實現(xiàn)揮動(wave)手勢識別的邏輯了。

6. 結(jié)語

本文主要介紹了手勢識別中設(shè)計的基本概念以及手勢識別的發(fā)展過程,在此基礎(chǔ)上介紹了手勢識別的三種基本方法:基于算法的手勢識別、基于神經(jīng)網(wǎng)絡的手勢識別和基于樣本庫的手勢識別。

本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務中斷的風險,如企業(yè)系統(tǒng)復雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉