當(dāng)前位置:首頁 > 嵌入式 > 嵌入式硬件

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

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

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

1. 什么是手勢

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

以上這些說明手勢在不同的學(xué)科領(lǐng)域都有自己獨(dú)特的含義。在學(xué)術(shù)領(lǐng)域都試圖對手勢定義一個(gè)抽象的概念。在用戶體驗(yàn)設(shè)計(jì)領(lǐng)域使用最廣泛的關(guān)于手勢的定義實(shí)在Eric Hulteen 和Gord Kurtenbach 1990年發(fā)表的一篇名為人機(jī)交互中的手勢(Gestures in Human-Computer Communication),定義如下:”手勢是身體的運(yùn)動(dòng),他包含一些信息。揮手道別是一種手勢。敲擊鍵盤不是手勢,因?yàn)橛檬种傅倪\(yùn)動(dòng)去敲擊按鍵沒有被觀察,也不重要,他只表達(dá)的鍵盤被按下這一動(dòng)作。(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)”

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

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

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

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

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

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

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

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

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

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

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

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

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

2. 自然交互界面(NUI)

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

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

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

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

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

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

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

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

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

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

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

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

雖然觸摸界面也有手勢,但Kinect 界面有些互動(dòng)不是手勢,不過軟件的開發(fā)和設(shè)計(jì)者傾向于以 Kinect 手勢操作作為交互界面。這似乎是因?yàn)槭褂檬謩葑鳛槲锢聿僮魇?Kinect 應(yīng)用程序的最大的特點(diǎn)。與此相反的是,觸摸界面的突出特點(diǎn)是直接操作。雖然可能不準(zhǔn)確,人們通常將自然交互界面劃分為三類:語音交互界面,觸摸交互界面和手勢交互界面。

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

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

3. 手勢從哪里來

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

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

image

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

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

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

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

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

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

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

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

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

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

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

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

4.1 基于算法的手勢識別

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

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

算法還有一個(gè)內(nèi)在的擴(kuò)展性問題。雖然一些代碼可以重用,但是每一種手勢必須使用定制的算法來進(jìn)行識別。隨著新的手勢識別算法加入類庫,類庫的大小會(huì)迅速增加。這就對程序的性能產(chǎn)生影響,因?yàn)樾枰褂煤芏嗨惴▉韺δ骋粋€(gè)手勢進(jìn)行識別以判斷該手勢的類型。

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

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

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

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

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

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

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

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

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

4.3 基于樣本的識別

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

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

5.識別常見的手勢

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

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

5.1 揮動(dòng)(wave)手勢

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

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

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

image

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

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

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

下面的代碼展示了記錄手勢識別狀態(tài)的兩個(gè)枚舉和一個(gè)結(jié)構(gòu)。第一個(gè)名為WavePosition的枚舉用來定義手在揮手這一動(dòng)作中的不同位置。手勢識別類使用WaveGestureState枚舉來追蹤每一個(gè)用戶的手的狀態(tài)。WaveGestureTracker結(jié)構(gòu)用來保存手勢識別中所需要的數(shù)據(jù)。他有一個(gè)Reset方法,當(dāng)用戶的手達(dá)不到揮手這一手勢的基本動(dòng)作條件時(shí),比如當(dāng)手在胳膊肘以下時(shí),可調(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):它定義了五個(gè)常量:中間區(qū)域閾值,手勢動(dòng)作持續(xù)時(shí)間,手勢離開中間區(qū)域左右移動(dòng)次數(shù),以及左手和右手標(biāo)識常量。這些常量應(yīng)該作為配置文件的配置項(xiàng)存儲(chǔ),在這里為了簡便,所以以常量聲明。WaveGestureTracker數(shù)組保存每一個(gè)可能的游戲者的雙手的手勢的識別結(jié)果。當(dāng)揮手這一手勢探測到了之后,觸發(fā)GestureDetected事件。

當(dāng)主程序接收到一個(gè)新的數(shù)據(jù)幀時(shí),就調(diào)用WaveGesture的Update方法。該方法循環(huán)遍歷每一個(gè)用戶的骨骼數(shù)據(jù)幀,然后調(diào)用TrackWave方法對左右手進(jìn)行揮手姿勢識別。當(dāng)骨骼數(shù)據(jù)不在追蹤狀態(tài)時(shí),重置手勢識別狀態(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的主體部分。它驗(yàn)證我們先前定義的構(gòu)成揮手姿勢的條件,并更新手勢識別的狀態(tài)。方法識別左手或者右手的手勢,第一個(gè)條件是驗(yàn)證,手和肘關(guān)節(jié)點(diǎn)是否處于追蹤狀態(tài)。如果這兩個(gè)關(guān)節(jié)點(diǎn)信息不可用,則重置追蹤狀態(tài),否則進(jìn)行下一步的驗(yàn)證。

如果姿勢持續(xù)時(shí)間超過閾值且還沒有進(jìn)入到下一步驟,在姿勢追蹤超時(shí),重置追蹤數(shù)據(jù)。下一個(gè)驗(yàn)證手部關(guān)節(jié)點(diǎn)是否在肘關(guān)節(jié)點(diǎn)之上。如果不是,則根據(jù)當(dāng)前的追蹤狀態(tài),揮手姿勢識別失敗或者重置識別條件。如果手部關(guān)節(jié)點(diǎn)在Y軸上且高于肘部關(guān)節(jié)點(diǎn),方法繼續(xù)判斷手在Y軸上相對于肘關(guān)節(jié)的位置。調(diào)用UpdatePosition方法并傳入合適的手關(guān)節(jié)點(diǎn)所處的位置。更新手關(guān)節(jié)點(diǎn)位置之后,最后判斷定義的重復(fù)次數(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軸左負(fù)右正.            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)中:這些幫助方法維護(hù)結(jié)構(gòu)中的字段,使得TrackWave方法易讀。唯一需要注意的是UpdatePosition方法。TrackWave調(diào)用該方法判斷手的位置已經(jīng)移動(dòng)。他的最主要目的是更新CurrentPosition和Timestamp屬性,該方法也負(fù)責(zé)更新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;    }}

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

6. 結(jié)語

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

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

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(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)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

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

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

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

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

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

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

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

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

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

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

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

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(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)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡稱"軟通動(dòng)力")與長三角投資(上海)有限...

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