from:http://viml.nchc.org.tw/blog/paper_info.php?CLASS_ID=1&SUB_ID=1&PAPER_ID=329
目前要在 Windows 上進行 Kinect 的應用程式開發,主要應該是有兩個選擇,一個是微軟官方的 Kinect for Windows SDK,另一個則是開放平台的 OpenNI。基本上,由於考慮到跨平台的問題、以及對於微軟的開發環境的一些疑慮,Heresy 自己是都使用 OpenNI 啦~對於微軟的 Kinect for Windows SDK,Heresy 基本上也只有大概看過而已,沒有真的在寫他的程式。
而由於兩者的驅動程式是不同的,所以一般來說,在同一台電腦上,是沒有辦法很方便地同時使用這兩種開發環境的。不過,也由於 OpenNI 的開放性,所以實際上在 Kinect for Windows SDK 的 Beta 版出來的時候,就已經有網友針對他作封包,寫出可以在 OpenNI 下使用的模組了~而這個模組,就是 Heresy 之前在《讓 OpenNI 可以透過微軟 Kinect SDK 讀取 Kinect 的資料!》一文中介紹過的「kinect-mssdk-openni-bridge」(官網)。
當時,這個「kinect-mssdk-openni-bridge」(以下簡稱為「Bridge」)是針對 Kinect for Windows SDK Beta 1 寫的,後來在新的 Beta 2、以及正式版推出出的時候,也都有更新;不過,對於 Kinect for Windows SDK 正式版的改寫,實際上算是晚了不少,一直到四月才有正式支援(的樣子)。
但是,最近作者似乎更新的相當勤勞!從四月初開始支援 Kinect for Windows SDK 1.0 開始,到現在已經改版好幾次、更新到 1.0.0.4 了~他不但針對正式版的 SDK 做了改寫,而且還支援 Kinect 的馬達控制、聲音擷取(包括聲音來源偵測、回音消除等功能)、以及新的 Kinect for Windows 硬體的「Near Mode」!
也因為這些功能的引進,目前來看他的功能可以說是相當地完整!在 Heresy 來看,如果是打算在可以安裝 Kinect for Windows SDK 的環境(Windows 7 / 8)下、進行 OpenNI + Kinect 的程式開發的話,搞不好使用這個「kinect-mssdk-openni-bridge」已經算是比 avin2 的「SensorKinect」更好的選擇了~
至於要怎麼使用呢?建議可以參考官方的「README_en.TXT」這個文件(連結),裡面有相當完整地說明。Heresy 自己沒有真的去玩,不過還是大概來列一下他的幾點比較重要的說明:
-
User Generator 的設定
首先,在 User Generator 的部分,主要是透過 production node 的名稱(name)來做使用上的控制。如果要在 OpenNI 內建立這個 bridge 提供的 user generator 的話,需要在建立時、透過 query 來加上名稱的指定。如果是使用 XML 來進行初始化(請參考《使用 XML 設定檔來初始化 OpenNI》)的話,他的寫法會是:
<OpenNI>
...
<ProductionNodes>
...
<Node type="User" name="User1">
<Query>
<Name>KinectSDKUserSkeletonGenerator</Name>
</Query>
</Node>
...
</ProductionNodes>
</OpenNI>
重點就是要加上 <Query>、並且指定 <Name> 為「KinectSDKUserSkeletonGenerator」了~
而如果是要寫在程式裡的話,則是使用 xn::Query 來做控制:
xn::Query mQuery;
mQuery.SetName( "MSRKinectUserSkeletonGenerator" );
xn::UserGenerator mUserGenerator;
mUserGenerator.Create( mContext, &mQuery );
另外要注意的是,這個 User Generator 是採用不需要標準校正姿勢的架構(請參考《不用校正姿勢的 NITE 1.5》),如果程式的人體骨架追蹤使採用早期、需要使用「Psi」 標準校正姿勢的架構來寫的話(請參考《透過 OpenNI / NITE 分析人體骨架》),那則需要把上面所使用的「KinectSDKUserSkeletonGenerator」這個名稱,改成「KinectSDKUserSkeletonGeneratorWithPsiPoseEmulation」來模擬 Psi 姿勢偵測的事件。
-
Depth Generator
深度感應器的建立方法,應該是沒有什麼特別的,和之前一樣使用就可以了;不過雖然深度感應器支援 QVGA(320x240)和 VGA(640x480)兩種解析度(MapOutputMode),但是就算設定為 VGA 模式,在有使用上面的 User generator 的情況下,解析度會被強制設定為 QVGA、然後模擬成 VGA,這是使用上可能要注意的。
另外,新版的 Bridge 也支援了 Kinect for Windows Hardware 的「Near mode」,要使用的話是透過 Depth Generator 的「nearMode」這個屬性(Property)來做設定;以 XML 來說,要啟用 Near mode 的寫法是:
<Node type="Depth" name="Depth1">
<Configuration>
<Property type="int" name="nearMode" value="1"/>
</Configuration>
</Node>
而對應到程式裡面,應該就是像下面這樣了:
xn::DepthGenerator xDepthGen;
xDepthGen.Create( mContext );
xDepthGen.SetIntProperty( "nearMode", 1 );
最後,Bridge 所提供的 depth generator 還可以設定讓深度值太近、太遠、以及未知的這三種狀況,回傳不同的值(OpenNI 預設這三種狀態都是無法偵測、都是回傳「0」);要控制這項功能的開啟與否的話,則是針對「distinctOverflowDepthValues」這個屬性來做控制,基本上方方法和上面的「nearMode」相同。
-
Image Generator
Bridge 所提供的 Image Generator 似乎只有提供 VGA(640x480) 和 1280x1024 @15FPS 這兩種解析度,似乎不支援 QVGA,這點是在使用時要注意的。
-
使用 Kinect 的馬達
Kinect 的馬達角度的控制,主要是透過 Image Generator、Depth Generator 或 User Generator 的「cameraElevationAngle」這個屬性來做控制的。他的設定方法,基本上就是下面這樣的形式:
XnUInt64 angle = 10;
xDepthGen.GetIntProperty( "cameraElevationAngle", angle );
xDepthGen.SetIntProperty( "cameraElevationAngle", angle );
另外,如果要進一步控制的話,也可以透過「nuiSensorPointer」這個屬性,來取得 Kinect for Windows SDK 裡的「INuiSensor」的物件指標、透過強制轉型的方法來進行操作;下面就是使用的範例:(個人是覺得這樣的用法還滿危險的…)
XnUInt64 i;
xDepthGen.GetIntProperty("nuiSensorPointer", i);
INuiSensor* pSensor = (INuiSensor*)i;
pSensor->NuiXxx(...);
這邊要注意的是,馬達的控制功能功能只有在開始產生資料(StartGeneratingAll())後才可以使用。
最後,這個版本的 Bridge 在 User Generator 的部分還提供了可以針對使用者自動調整馬達角度的功能!要開啟這項功能,則是要把 User Generator 的名稱,從本來的「KinectSDKUserSkeletonGenerator」改成「KinectSDKUserSkeletonGeneratorWithAutoElevation」。
-
聲音的取得
Audio Generator 的部分,其實 Heresy 自己在 OpenNI 也都沒有用過,所以其實也不是很熟。而在這邊,Bridge 所提供的 Audio Generator 除了可以取得原始聲音資料外,應該是也把 Kinect for Windows SDK 針對聲音做處理的各項功能以屬性的方式移植過來了~ 下面就是他的 XML 設定的說明:
<Node type="Audio" name="Audio1">
<Configuration>
<!-- Beam forming mode
0: Adaptive (Controlled by Kinect-specific DSP)
1: Automatic (Controlled by DMO)
2: Manual (Controlled by the application via the beamAngle property
explained later) -->
<Property type="int" name="beamAngleMode" value="0"/>
<!-- Automatic gain control: 0(off), 1(on) -->
<Property type="int" name="automaticGainControl" value="0"/>
<!-- Echo cancellation (AEC) and suppression of residual signal (AES)
0: None
1: AEC
2: AEC and AES once
3: AEC and AES twice -->
<Property type="int" name="echoCancellationMode" value="2"/>
<!-- Center clipping (a technique to remove the residual signal after AEC) and
Noise filling (a technique to make the sound natural by using a small
amount of noise instead of silence after removing the residual signal)
0: None
1: Center clipping
2: Center clipping and Noise filling -->
<Property type="int" name="centerClippingMode" value="0"/>
<!-- Noise suppression: 0(off), 1(on) -->
<Property type="int" name="noiseSuppression" value="1"/>
<!-- Audio buffer size in milliseconds. The audio data is
lost unlsee the application polls the audio data
within this interval. Set before StartGenerating. -->
<Property type="int" name="bufferSizeInMs" value="1000"/>
</Configuration>
</Node>
而在程式中要取得相關的數值的話,基本上就是:
double beamAngle, sourceAngle, sourceAngleConfidence;
audioGenerator.GetRealProperty("beamAngle", beamAngle);
// read-only or read-write when beamAngleMode is manual
audioGenerator.GetRealProperty("sourceAngle", sourceAngle);
// read-only
audioGenerator.GetRealProperty("sourceAngleConfidence", sourceAngleConfidence);
// read-only
這篇大概就是這樣了。不過也提醒一下,實際上 Heresy 並沒有真的去用過,只是照著文件來寫的。而如果有使用上的問題,建議也可以直接到作者在官方論壇所發的《KinectSDK 1.0 + OpenNI/NITE at the same time (Part 2)》這串討論來看看、提問。
而在 Heresy 來看,他比較可惜的一點,就是他不支援 64 位元版、只支援 32 位元版了…所以就算是 64 位元的電腦,還是只能使用 32 位元的 OpenNI。