Kinect hacking 101

當mmdays說要來個showtime時,其實我還蠻緊張的,這兩年來,除了頭頂微禿,小腹更凸以外,我沒寫過一篇文章,尤其當我把我的主要OS換成Ubuntu以後,連中文都很少打了(大家都知道Linux的中文輸入法很難用),要寫什麼主題可讓我著實煩惱了很久,畢竟這可是mmdays,不能像普通blog一樣寫:我今天上班很開心,因為公司的正妹對我笑了一下,回家煮完飯,看完Boardwalk Empire (注:HBO的新劇,很好看),然後就睡覺了,這樣寫得話,我一定會被其他days打死,就在我不知如何是好時,我突然發現我身邊的新玩具,那就來寫這個好了。

為了避免有人不知道Kinect是什麼,我就先來介紹一下好了,Kinect是微軟為Xbox360新出的一個控制系統,想當初Nintendo Wii那個感應手把帶給了人們一種新的體驗-打電動不在是按按鈕而已,你必須揮動著遙控器跟螢幕中的虛擬人物互動,讓打電動進入了一種新的層次,也造成了Wii的熱賣和其他對手的眼紅,但是畢竟這種科技不是一下子就能搞出來的,在Wii紅了三年多以後,其他家終於出了類似的技術,其中Sony PS3推出的,叫做PS move,包含了一個攝影機,和一個像是仙女棒的東西,用法跟Wii很類似,但是因為用了攝影機來作定位,可以更加的精準感應手的位置和方位。雖然技術更先進了,但是形式卻跟Wii沒兩樣,但是微軟推出的Kinect卻做了出了一個創舉,就是把那個仙女棒拿掉了,Kinect不再利用手上的遙控器來感應實際的位置,而是用三個攝影機來定位你的動作,這又給打電動事業帶入了一個新的層次,第一,這樣感應的就不再侷限是你的手,你的全身皆可以感應得到,第二,你不用每次要玩之前,都要花十分鐘找你的仙女棒(這大概只有我吧)。說再多,還不如用看得,我附了三個遊戲機的宣傳影片,這樣假如你完全不了解我之前在講什麼,看影片應該會比較清楚。

當然假如我這篇是在介紹Kinect有多好玩,那個遊戲特別值得推薦的話,那我應該在巴哈姆特寫這個文章,而不是mmdays了,事實上,我Kinect買來第一天,我玩了一次,就被我裝在電腦上了,大家不覺得這麼有趣的東西,只能玩遊戲太可惜了嗎?我能不能像關鍵報告一樣,雖然沒有Tom Cruise這麼帥,但是至少也能像他一樣帥氣的操作電腦呢?今天 KH101(我自己亂取的課程代碼,通常101是大學剛入學的第一堂課的編號)就來給大家提個概念。

kinect

圖片來源: Engadget

在一開始的,我們得先了解一下Kinect的硬體規格,Kinect一共用三個類似攝影機,中間那個就是我們常見的普通webcam,這個鏡頭有8 bit的VGA解析度(640×480 相素..這我晚點會說明這是什麼意思),基本上就跟普通的webcam沒兩樣,但是左右兩個可就是Kinect中最重要的秘密武器,由一家以色列公司(PrimeSense)推出的可以測景深的裝置。

圖片來源:PrimeSense

我們可以看到它左邊其實不是攝影機,而是投影機,但是投出的並不是可見光,而是紅外線光(IR light),所以你並不會感覺到有光照在你身上,另一個則是一個CMOS的攝影機,根據投出的紅外線光影像來根據影像計算景深,這個景深攝影機的解析度一樣是VGA(640×480像素),有11 bit的色階。

這張就是從景深攝影機出來的圖(我轉成了16bit的圖片)

我剛剛說了一堆VGA,11bit東西,為了怕有人不是很了解,在此順便解說一下,這些規格代表了什麼,到底有什麼意義呢?我記得小時後有本參考書叫做點線面(知道的人應該..嗯嗯..年紀不小),大家都知道一條線是由無數眾多的點集合而成的,面則是無數多條線集合而成的,我們說無數條,那到底有多少條呢?這時剛剛提出的數據就有用了,大家都知道圖片呢,就是一個面,640*480就是代表一條線(橫線)有640個點,一個面有480條線,那個什麼8 bit 11bit又代表什麼意思呢?那是代表這張圖的色階的深度,我們剛剛說假如一張圖的解析度是640×480,這張圖則一共有640×480=307200個點,每個點都有一個顏色,眾多顏色排列起來,就是我們現在看到的圖片,這時另一個問題來了,那那個點可以顯示多少顏色呢?大家可能會想那有什麼問題,當然是越多越好,但是事實不是這樣的,因為顏色越多,代表這張圖要存的資料,也就是檔案越來越大,於是定義色階變成了很重要的事,所謂的8 bit呢,就是所謂的2的8次方也就是256,代表了這個點呢,可以顯示出256種顏色,那11bit呢,則是2的11次方,也就是2048種顏色。在這邊得說明一下,剛剛說那個webcam的攝影機是8 bit,那不是只有256色嗎?難道微軟認為我們的花花世界只需要256色就可以表示了嗎?當然不是的,所謂的8 bit是指一個channel有8 bit,大家應該聽過這個自然界有三原色,就是這個世界上的顏色都是三種顏色的混合,這三個顏色分別是紅色,綠色,和藍色,所以那個攝影機一共有三個channel分別給這三原色,然後每個原色有256階的變化,所以總共的顏色是256*256*256 = 16.7 millions色。

這張就是所謂的灰階 8 bit圖表(來源:wikipedia

最後我還得補充一個就是,kinect上面裝的是攝影機,不是照相機,大家都知道所謂的影片就是一連串的圖片快速播放出來的,它的規格是每秒30張圖片,顧名思義,它一秒會跑出30張圖片出來。

花了這麼多心思解釋這圖像原理是有關系的,畢竟要hack kinect,影像處理的概念是必須的,接下來我們要進入最重要的主題 – Kinect hacking,這時我們要先感謝網路的發達,在kinect發行一個月內,就有神人把kinect的驅動程式寫出來了,這樣原本最難的部份,一下子就變成最簡單的部份,而且無論你是用Windows, Mac, Linux 每個版本的驅動程式都有,而且是Open Source,更好的是上禮拜,PrimeSense這個主要晶片公司看大家這麼努力,也把他們的驅動程式也release出來,並且也open source,和他們的骨架辨識程式(這個沒有open source)叫做Nite。我自己是用神人寫的驅動程式,接下來的說明基本上也是以這個版本為主。

有了驅動程式,那我們裝好就萬事大吉了嗎?其實並沒有,沒有配套的應用程式,你的Kinect就只是會有一個會閃綠燈的裝飾品而已,今天我們就來說說,要怎饃來寫這個配套的應用程式,從神人的驅動程式裡,你會得到兩種資料,一個是景深的資料,另一個是RGB的資料,RGB並不是我們今天的重點,所以我們先跳過它,再來我們來看看景深的資料,景深的資料是一個640 x 480矩陣( or Array),裡面是全部都是從0~2047的數字,黑,大家有沒有覺得很熟悉,這樣大家應該了解為什麼我之前花了這麼大段寫圖像的構成原理,沒錯,那就是我之前提到11bit的值,因為電腦大部分都是從0計數,所以是0~2047,一共2048個值,那個矩陣裡的每一個點分別對應了攝影機裡的畫面的位置,那些數字就是分別了代表了景深的資料,但是這些數字代表了什麼東西呢?怎饃把這些數字轉換成更現實的東西呢?這時我們必須再度感謝網路的偉大,已經有人算出公式讓你可以把這些數值轉成公分,distance = 100/(-0.00307 * rawDisparity + 3.33)(注:假如你用原廠的驅動程式,有直接轉換的function),有了這些資料,我們能幹什麼呢,想想看,我們人看到的東西時,我們可以很容易的分辨出這是一個東西,即使東西旁邊有一堆亂七八糟的其他東西,我們也可以很容易知道找到那個東西,這就是人腦厲害的地方,但是電腦就不一樣了,它看到的是一張圖,裡面有一堆代表顏色的像素,要怎饃把那個東西跟其他東西分離開來,那可不是件容易的事,但是有了景深的資料就不一樣了,我們可以靠每樣東西離攝影機的距離的不同,把我們不想要的背景分離開來。請各位參照一下下面右邊跟左邊的照片,左邊是過濾背景資料,右邊是沒有過濾過得,我只做了一很簡單的分離,我把距離攝影機50cm~90cm之間的東西留下來,其他我不要,手就變成唯一留下來的東西,這樣我們就很容易把我們需要的物體找出來。

我們得到手以後呢,那又怎饃樣呢?就像我剛剛說得,這些全部都是放在一個640×480的圖片裡,對電腦而言,那只是是由一堆黑點構成的和白點構成的圖,假如那我們要感應手的移動,那我們應該要先找出手的位置,然後比對下一張圖手得位置,假如下一張手的位置是在前一張圖手的位置右邊,那電腦就知道手往右邊移動了,但是要如何找出手實際的位置變成了一個難題,畢竟對電腦而言,這也只是一張張得圖片,這其實作法其實很多種,首先,假如我們需要的是移動的資料的話,我們可以用前一張圖和後一張圖來作比較,這樣我們可以比較黑點位置的變化,然後取平均值,這樣就可以得到手的移動距離,另一種方法則是比較簡單的方法,也是我們今天要介紹的,就是給手畫框框,其實我們想知道的只是那隻手中間一個黑點得位置,那個點當然不能亂選,它必須能代表那隻手的位置,所以是越中間越好,但是大家也知道那個手長完全不規則型,要抓中間點不是件容易的事,那假如我今天能夠劃一個框框把那個手包住,然後取框框的中間點,那個中間點不就能代表手的位置了嗎?那個框框很容易劃,我只要找出最左邊的黑點,最上面的黑點,最下面的黑點,和最右邊的黑點,那我的框框不就可以畫出來了。

現在大家就可以看到那個框框,這樣我就可以取那個框框的中間值,然後我只要追蹤那個值,這樣我就可以知道手的移動路徑了,不是嗎?

話說大家有沒有發現這個作法有一個致命的缺點,就是萬一我有兩隻手怎饃辦,我想要multi-touch時,我要怎麼分離兩個物體,然後給物體畫框框呢?黑黑,那個就不屬於這個初級課的範圍啦,不過我可以給一個小小地暗示,可以google opencv這個library,它能做出你想要得東西。

附一段結果影片(大家可能會發現沒這麼精準,是因為我沒有作效正的動作,校正則是另一門學問,有機會再說)

對了我忘了說教科書,和該讀得文章,記得要唸喔,下禮拜要考試:)

OpenKinect (神人寫得驅動程式)

OpenNi (PrimeSense的驅動程式)

PrimeSense Tech Spec

Learning OpenCV – Computer Vision with the Open CV Library (蠻值得讀得一本書)

喜歡這篇文章嗎? 分享出去給作者一點鼓勵吧!