在之前的 OpenNI 2.2.0.21 版裡面,OpenNI 算是終於把 Kinect 的 Image registration 功能加進來了~這點,對於要考慮使用不同裝置來開發的人,基本上應該已經算是比以前方便不少了;不過很遺憾,他還是不支援鏡像(mirror)的功能。除此之外,Kinect 感應器本身的馬達、加速度感應器、以及 Kinect for Windows 感應的「Near Mode」,也都還是不能使用的。
由於 Heresy 前一陣子在研究 OpenNI 2 的驅動程式模組(參考)、也寫了一個 WebCam4OpenNI2;後來想想,反正都大概知道該怎麼做了,那與其等別人寫,倒不如自己試著改看看吧~所以,就把這些功能都補上了。這部分的修改,目前已經在 OpenNI 那邊建立 pull request(#22)了,但是目前還沒被整進去;不過如果想看怎麼改的話,應該是可以直接在 GitHub 上看到。
而如果只是想下載來用的話,可以到
這邊下載;在 x64 下,就是 64 位元的 Kinect.dll,x86 下則是 32 位元的版本。要使用的話,只要把這個檔案下載後,取代掉原來的 Kinect.dll 就可以了。(\OpenNI2\Drivers\ 目錄下)
這個版本提供的功能,包括了:
- 鏡像(mirror)
- 感應器角度(KINECT_DEVICE_PROPERTY_CAMERA_ELEVATION)
- 感應器加速度感應器資料(KINECT_DEVICE_PROPERTY_ACCELEROMETER)
- 深度的 Near Mode(KINECT_DEPTH_PROPERTY_NEAR_MODE)
要測試鏡像的功能的話,由於是 OpenNI 本身就定義好的介面,所以可以直接呼叫 VideoStream 的 setMirrorEnabled() 來做控制;不想自己改程式的話,則可以用官方的 NiViewer 來試看看(按鍵盤的 m)。
至於其他的功能,則是定義在 Heresy 自己加入的 KinectProperty.h 這個檔案裡,可以透過 Device 或 VideoStream 的 getProperty() / setProperty() 來做存取;下面是簡單的說明:
-
感應器角度(KINECT_DEVICE_PROPERTY_CAMERA_ELEVATION)
用來讀取、設定 Kinect 的上下傾角用的,適用於 Device,資料型別是 long,可以讀取也可以寫入。下面是一個使用範例:
long value;
m_device.getProperty( KINECT_DEVICE_PROPERTY_CAMERA_ELEVATION, &value );
m_device.setProperty( KINECT_DEVICE_PROPERTY_CAMERA_ELEVATION, value 1 );m_device 是一個對應到 Kinect 的 openni::Device,透過 getProperty(),可以把目前的角度讀取出來、寫到 value 這個型別為 long 的變數裡;透過 setProperty(),則可以指定所需要的角度、來控制 Kinect 的馬達。 在上面的例子裡,就是去讀取現在的角度後、設定讓它抬高 1 度。
內部實際是去呼叫 Kinect for Windows SDK,INuiSensor 的 NuiCameraElevationGetAngle() 和 NuiCameraElevationSetAngle() 這兩個函式;詳細可以參考 MSDN 的說明(連結一、連結二)。
 
-
感應器加速度感應器資料(KINECT_DEVICE_PROPERTY_ACCELEROMETER)
這是用來讀取 Kinect 內部的加速度感應器,用來判斷 Kinect 目前的方向的。一樣是適用於 Device,資料型別是 KVector4,裡面是四個 float,代表目前加速度的方向,如果 Kinect 是完全水平的話,他的值會是 ( 0, -1, 0, 0 )、代表指向下方。這個值只能讀取、不能設定;下面是一個簡單的讀取範例:
KVector4 vec;
m_device.getProperty( KINECT_DEVICE_PROPERTY_ACCELEROMETER, &vec );
printf( "%f, %f, %f\n", vec.x, vec.y, vec.z );一樣,透過 Device 的 getProperty() 可以把結果寫到 vec 這個 KVector4 的變數裡面。
(注意:Heresy 沒有去處理 Kinect for Windows SDK 和 OpenNI 座標系統的問題)內部實際是去呼叫 Kinect for Windows SDK,INuiSensor 的 NuiAccelerometerGetCurrentReading() 這個函式;詳細可以參考 MSDN 的說明(連結)。
 
-
深度的 Near Mode(KINECT_DEPTH_PROPERTY_NEAR_MODE)
這是用來設定 Kinect for Windows SDK 的「Near Mode」的功能。適用於深度影像的 VideoStream,資料型別是 OniBool(OpenNI 定義的布林變數),可以讀取也可以設定。下面是簡單的使用範例:
OniBool flag;
m_depthStream.getProperty( KINECT_DEPTH_PROPERTY_NEAR_MODE, &flag );
m_depthStream.setProperty( KINECT_DEPTH_PROPERTY_NEAR_MODE, !flag );這邊的 m_depthStream 是對應到 Kinect for Windows 感應器深度影像的 openni::VideoStream,透過 getProperty(),可以把資料寫到 flag 這個 OniBool 的變數裡,用來判斷目前是否有開啟 Near Mode;而透過 setProperty() 則可以設定是否要切換到 Near Mode。在上面的例子裡,就是會先讀取現在的模式、然後設定成另一個模式。
內部實際是去呼叫 Kinect for Windows SDK,INuiSensor 的 NuiImageStreamGetImageFrameFlags() 和 NuiImageStreamSetImageFrameFlags() 這兩個函式;詳細可以參考 MSDN 的說明(連結一、連結二);不過說實話,Heresy 不太確定這邊的寫法是否完全正確。
另外,在 SkyDrive 上的「SampleViewer」目錄裡的 Viewer.cpp 這個檔案,則是根據官方的「SampleViewer」這個範例(\Samples\SimpleViewer)做修改的;裡面會在每次更新畫面的時候,都讀取加速度感應器的資料並輸出,而如果按下鍵盤的「n」,則可以切換 near mode 的開關,按下鍵盤的「 」和「–」,則可以每次一度、控制感應器的上下傾角(不過好像會造成一定程度的延遲)。
大致上就是這樣了。由於 Heresy 自己也算是剛寫完、並沒有做很嚴謹的測試,所以如果有人有發現問題的話,就麻煩回報一下吧~
heresy您好,这几天在研究怎么确定kinect姿态矩阵的问题,正好昨天看到了您发布的博文,对我的帮助很大,在此先谢谢了.另外,您说里面感應器加速度感應器資料可以得到kinect的姿态角,那可不可以给定一个初始位置,然后通过对三个轴的加速度算积分,不仅得到kinect的姿态角,并且得到它离初始位置的位移矢量呢?
@初心者
Heresy 不確定這個資料是否可以做到你想做的事。
因為實際上就算平放的時候,他也會有一個向下的向量(地心引力),你如果要計算累計位移的話,就必須先排除他才行。Heresy 不確定這個值是否可以這樣使用。
谢谢您的回答,另外我还想请问Heresy,KVector4的第四个变量w是指的什么呢?为什么我在运行程序的时候w总是0呢?
@初心者
http://openhome.cc/Gossip/ComputerGraphics/HomogeneousCoordinate.htm
https://zh.wikipedia.org/wiki/齐次坐标