透過 OpneNI 讀取 Kinect 深度影像資料

| | 84 Comments| 17:30
Categories:

前一篇文章已經大概針對 OpenNI 的架構做了一些說明,而這一篇就來針對如何使用 OpenNI 讀取微軟的 Kinect 的影像資料吧!

而先說明一下,Heresy 這篇文章是使用 Visual C 2010,針對目前微軟的 Kinect、SensorKinect 的驅動程式,搭配 1.0.0.23 版的 OpenNI 版寫的;如果使用其他版本、或是其他支援 OpenNI 的裝置,那可能會要做一些對應的修改。同時,在開始閱讀這篇文章前,建議也請先參考《在 WIndows 上安裝 Kinect(含 MMD 使用 Kinect 簡易教學)》來安裝 Kinect 和 OpenNI,並確定可以正常運作。

首先,OpenNI 他預設的安裝路徑是在「C:Program FilesOpenNI」,要開發 OpenNI 程式所有必要的檔案,都會在這裡;而在資料夾內,除了「Documentation」裡有提供兩份文件可以用來當作開發程式的依據外,在「Samples」目錄下,也有提供不少範例可以用來參考。

OpenNI 的核心基本上是 C 語言,不過他有提供 C 的 Wrapper 來當作 C 使用;基於個人習慣的關係,Heresy 在這邊會以 C 的形式,來使用 OpenNI。而必要的 header 檔,都會在 OpenNI 的「Include」目錄內,連結程式時所需的 openNI.lib 這個檔案則是在「Lib」裡。不過要注意的是,OpenNI 目前在 Windows 環境下只有 32 位元的版本、沒有 64 位元版,所以目前只能編譯 32 位元的 OpenNI 程式。

而要設定一個使用 OpenNI 的 Visual C 專案也很簡單,只要在專案「C/C Additional Include Directories」裡加入「$(OPEN_NI_INCLUDE)」、「Linker Additional Library Directories」裡加上「$(OPEN_NI_LIB)」,並在「Linker Additional Dependencies」裡加上「OpenNI.lib」,這樣就可以了。

而接下來,Heresy 就先以讀取 Kinect 的深度影像資訊為目標,來寫一個 C 的範例程式了∼他的程式碼如下:

#include <stdlib.h>
#include <iostream>
#include <string>

#include <XnCppWrapper.h>

using namespace std;

void CheckOpenNIError( XnStatus eResult, string sStatus )
{
if( eResult != XN_STATUS_OK )
cerr << sStatus <<
" Error: " << xnGetStatusString( eResult ) << endl;
}


int main( int argc, char** argv )
{
XnStatus eResult = XN_STATUS_OK;

// 2. initial context
xn::Context mContext;
eResult = mContext.Init();
CheckOpenNIError( eResult,
"initialize context" );

// set map mode
XnMapOutputMode mapMode;
mapMode.nXRes = 640;
mapMode.nYRes = 480;
mapMode.nFPS = 30;

// 3. create depth generator
xn::DepthGenerator mDepthGenerator;
eResult = mDepthGenerator.Create( mContext );
CheckOpenNIError( eResult,
"Create depth generator" );
eResult = mDepthGenerator.SetMapOutputMode( mapMode );

// 4. start generate data
eResult = mContext.StartGeneratingAll();

// 5. read data
eResult = mContext.WaitAndUpdateAll();
if( eResult == XN_STATUS_OK )
{
// 5. get the depth map
const XnDepthPixel* pDepthMap = mDepthGenerator.GetDepthMap();
// 6. Do something with depth map
}
// 7. stop
mContext.StopGeneratingAll();
mContext.Shutdown();

return 0;
}

這個程式的功能,基本上就是去透過 OpenNI 讀取一張解析度 640 x 480 的深度資訊影像;但是在讀取到資料後,並沒有針對取得的資料做任何事,所以如果沒有問題的話,這個程式是會直接結束,而沒有任何產出的。

接下來,就來仔細看程式碼的部分。

  1. Header

    首先,要以 C 的形式使用 OpenNI 的話,只需要加入「XnCppWrapper.h」這個標頭檔就好了,不用再 include 其他的檔案。而 OpenNI 定義了名為「xn」的 namespace,所有的物件,大多都在這個 namespace 內,而不在 namespace 內的東西,也都有 XN 這個 prefix,所以應該還算滿好區分的。

  2. 初始化 context

    要使用 OpenNI,要先建立一個型別為「xn::Context」的 conext 物件(這裡就是「mContext」),用來管理整個 OpenNI 的環境狀態以及資源;而在開始使用前,必須要呼叫它的成員函式「Init()」來進行起始化(上方程式碼「initial context 」的部分)。在進行起始化的時候,所有 OpenNI 相關的模組會被讀取、分析,直到呼叫「Shutdown()」這個函式,才會把所使用的資源釋放出來。

  3. 建立、設定所需要的 Production Node

    在 context 起始化成功後,接下來是要建立所要使用的 production node 了。由於這個範例的目的只是要讀取深度感應器的資料,所以這裡要建立的就只有「depth generator」一種,他的型別是「xn::DepthGenerator」。  而建立一個 production node 的方法,則是先宣告出他的物件(這裡就是「mDepthGenerator」),然後再去呼叫他的「Create()」函式,並把 context 傳入,這樣就可以了(上方程式碼中「create depth generator 」的部分)。
    不過要注意的是,有的時候在建立出 node 後,還需要對這個 node 作一些設定。像在這邊,就還必須要透過「SetMapOutputMode()」這個函式,來設定 mDepthGenerator 這個 depth generator 的輸出模式;而以 Kinect 來說,是要設定成為 640 x 480、30FPS。

  4. 開始產生資料

    在必要的 production node(這邊只有一個)都建立好了以後,接下來就是開始產生資料(generate data)了!由於 OpenNI 的概念是所以屬於 generator 的 production node(名稱裡有 generator 的都是)在使用時,都會不停地產生資料,所以得透過 context 來統一控制資料讀取的開關。
    而控制的方法很簡單,就是透過 context 的成員函式「StartGeneratingAll()」來開始、並透過「StopGeneratingAll()」停止。在一個 context 執行「StartGeneratingAll()」開始讀取後,屬於他的 generator node 都會開始產生資料,直到呼叫「StopGeneratingAll()」才會停止。

  5. 讀取資料

    在開始產生資料後,就可以讀取各個不同的 production node 的資料了∼不過不同類型的 generator 必須要透過不同的函式來讀取資料,像這邊的 depth generator 就是要用「GetDepthMap()」這個函式,來取得目前的 depth map。而 Depth Generator 取得的資料,會是一個「XnDepthPixel」的 const 指標,指向他實際資料的空間。

    不過這邊另外要注意的就是,generator 雖然是會不停地讀取新的資料,但透過「GetDepthMap()」這類的函式,是有可能會拿到舊的資料的。而為了確保能取得最新的資料,在讀取 Generator 的資料前,都必須要先呼叫 context 的 wait / update 這一系列的函式,來進行 node 資料的更新。
    這系列的函示有四個:WaitAnyUpdateAll()WaitOneUpdateAll()WaitNoneUpdateAll() 和這邊所使用的 WiatAndUpdateAll()。這四者都會更新 context 下所有的 node 的資料,差別只在於更新的條件;Heresy 這邊所使用的 WiatAndUpdateAll() 會等到所有的 node 都取得新資料後,再統一更新所有的 node 的資料;而 WaitAnyUpdateAll() 是等到隨便一個 node 有新資料時就會更新、WaitOneUpdateAll() 則是等到指定的 node 有新資料時再更新、WaitNoneUpdateAll() 則是不管有沒有新資料就強制更新。基本上,這四個不同的函式就是自己看時機、需求使用了。

  6. 處理讀取到的資料

    前面已經有提過了,Depth Generator 取得的資料,會是一個「XnDepthPixel」的 const 指標、而實際上它就是一個大小是 640 x 480 的一維陣列(因為現在的輸出模式是 640 x480),基本上可以把它看作一張 640 x480 的灰階圖片,其中每一個點都代表他的在這個位置的深度、型別是「XnDepthPixel」;而他的深度值在 Windows 32 位元的平台上,型別應該等同於「unsigned short」。基本上,這裡的深度值越大、代表距離越遠(0 則是代表該點深度無法判別),如果透過 OpenNI 的函式,也可以換算出絕對距離,不過在這篇文章暫時不會提到就是了。

    在這個範例程式裡,Heresy 什麼事都沒有做。如果要額外處理這個深度圖的資料的話,只要在「// 6. Do something with depth map」那裡,讀取「pDepthMap」這個指標的資料來做處理就可以了。像如果把直接它的深度資訊由 XnDepthPixel 轉換為一般的 256 灰階圖輸出的話,就會是類似右邊的結果;而當然,這樣的圖意義不大,但是其實這些深度資訊還可以拿來做很多應用,這點就看程式開發者怎麼發揮了∼
    (Heresy 本來有想連儲存圖檔一起寫,不過由於牽扯到儲存圖檔的話,程式碼會變得比較複雜,所以在這邊也就先跳過了)

  7. 結束

    當讀取完資料,不再繼續讀取資料後,就要把 OpenNI 停下來;而這邊為了停止繼續產生資料所呼叫的函示,就是之前已經提到過的「StopGeneratingAll()」。而如果完全不打算繼續使用 OpenNI 的環境的話,則也要記得呼叫「Shutdown()」這個函式,把 OpenNI 所使用的資源釋放出來。

  8. 錯誤偵測

    如果仔細看前面的程式碼應該可以發現,Heresy 在大部分的地方都用一個型別是「XnStatus」的變數「eResult」來接 OpenNI 函式的回傳值,而實際上,這就是用來判斷 OpenNI 的函式是否正確執行的依據;如果一個 OpenNI 函式的回傳值式「XN_STATUS_OK」的話,就代表他執行結果是正確的,但是如果不是的話,就代表可能出問題了∼而要知道出了什麼問題,則可以透過「xnGetStatusString()」這個函式,來取得文字的錯誤訊息;像上面 Heresy 自己定義的「CheckOpenNIError()」,就是在做這件事的。

這篇 Kinect OpenNI 的第一個範例,就大概先寫到這了。基本上,這篇算是透過抓取深度的範例,來大概解釋一下怎麼使用 OpenNI 裡的 map generator 了∼而這邊的程式也相當單純,之後還會再慢慢寫一些更進階的應用的。

84 thoughts on “透過 OpneNI 讀取 Kinect 深度影像資料”

  1. 如果要把讀到的深度資料輸出成灰階圖案是不是還要用到OpenGL的繪圖呢?

  2. to starmaplecloud@hotmail.com如果只是想存檔的話,就不需要用到 OpenGL,只需要找一個可以處理影像檔案存取的函式庫就可以了。例如要存 TIFF 的話,就可以用 libtiff;或者 BOOST 裡也有基本的圖形檔案存取函式庫。不過要注意的是,一般的灰階圖檔是 8bit 的(一般適用 unsigned char),而 OpenNI 的深度資訊 unsigned short,所以可能會需要經過轉換。

  3. Heresy大大您好:小弟想請教您一下當Depth Generator取得資料後他的資料是什麼?像是您之前寫的骨架偵測是以x y z 座標的形式來呈現那Depth Generator資料是以何種方式呈現呢可否把那些資料給呼叫出來不好意思問得有點多 感謝您:)

  4. to Chen,Yuan 這篇就是在講你問的事情啊…麻煩請參考文章中「 6.處理讀取到的資料」的部分

  5. 您好,我想請教下,如果我想選擇特定的深度來獲取部分圖像的話,應該怎麼做才能選擇特定的深度呢?

  6. 不好意思, 再請教一個膚淺的問題,您能否把下面這段話再具體解釋下?這三步具體怎麼實現。謝謝。只要在專案「C/C Additional Include Directories」裡加入「$(OPEN_NI_INCLUDE)」、「Linker Additional Library Directories」裡加上「$(OPEN_NI_LIB)」,並在「Linker Additional Dependencies」裡加上「OpenNI.lib」,這樣就可以了。

  7. to ouchou 深度的問題,建議你把深度圖完整抓出來後,在整個掃一遍,把你要的資料找出來。而設定的部分,請參考 Visual Studio 本身的說明。基本上,這些設定都在是專案的屬性裡面進行設定的。

  8. Heresy大大您好,我看例程里都没有定义Using namespace std这一句,而且我发现#include,似乎与例程中的文件SceneDraw.cpp起冲突,我现在想借用您写的程序修改例程,请问应该如何融合二者呢?

  9. @Chocolate 抱歉,不太確定你的問題是什麼?基本上,Heresy 這邊使用到的函式庫,除了 OpenNI 外,就只有 STL 了;由於 STL 是很基礎的 C 標準函式庫,基本上不太可能會和其他程式有不相容的問題才對。而是否要加上 using namespace,只是看個人程式習慣,不加也是可以的,只是會變成在使用時,並須指定 namespace 而已。

  10. heresy大大,您好,我想问如果将采集的数据保存成图文件的话,OpenNI有专门的函式库还是结合OpenCV来做,谢谢您了。

  11. to NireyflipOpenNI 本身沒有提供影像檔案的讀取和儲存介面,有需要的話你必須要搭配其他函式庫使用。除了 OpenCV 是一個方案外,也有許多影像處理的函式庫可以使用。

  12. 谢谢heresy大大想再问您一个问题,想问哪里有OpenNI的API文档…想学习学习..麻烦了

  13. to Nireyflip OpenNI 的 API 說明文件裝完 OpenNI SDK 就有了吧?

  14. heresy大大。。。我抄写了您的程序,编译什么的都通过了可是运行程序的时候为什么没有图像出来呢?您的qq是多少可以加我指点指点我么,最近刚用kinect,我的qq是289579417

  15. to jx建議您仔細閱讀一下文章、以及程式碼。這個範例程式裡面,並沒有包含任何圖像顯示、輸出的功能,所以理所當然不會有畫面出現。有畫面的版本,可以參考《使用 Qt GraphicsView 顯示 OpenNI 影像資料》http://viml.nchc.org.tw/blog/paper_info.php?CLASS_ID=1&SUB_ID=1&PAPER_ID=254

  16. 呵呵谢谢您的指点昨天我把深度图像信息显示出来了,现在我想把图像里的每个点的像素值给提取出来,能指导指导我怎么提取么,图片保存在Mat m_DepthShow( 480,640,CV_8UC1);这个里面

  17. to jx抱歉,Heresy 沒有在寫 DirectX 的程式。不過基本上 depth map 就是一個 array 的資料,基本上要處理都不會是什麼大問題。詳細方法請自行參考所使用的 Library 的文件(以你這邊來說,就是要去看 Direct Show 的文件)

  18. 想問一下!如果我想要在Kinect 不透過openNI,彩色圖像跟深度一併儲存,這樣能做到嗎?我已經找到彩色圖像的相關文章,我想要了解深度影像儲存需要用那些事件跟方法,麻煩您了。謝謝。

  19. to QD您好。基本上,OpenNI 是一種用來存取 Kinect 這類的裝置的一種 SDK;而你如果不希望用 OpenNI 的話,基本上還是需要使用別種類似的 SDK(例如微軟自己的 Kinect for Windows SDK)。如此一來,重點只是你要用哪種 SDK、和要用哪種方法來儲存而已。程式要怎麼寫,則是要取決於你要用那些套件。

  20. 請問版主,如果我是要結合滑鼠把影像和深度圖的其中一點抓出來,把3D的位置傳出來做使用,具體該怎麼做呢。謝謝版主長期以來的分享,小弟受惠良多

  21. to YUCK 基本上,應該只要把滑鼠的座標換算成 depth map 的投影座標、然後再去取那點的值就可以了?接下來你要怎麼用,應該是看個人需求了。

  22. 博主你好! 我按照你所讲的,用VS2008进行了编译,没有错误;但是在运行的时候,depth generator一直都无法获取到数据。 我单独测试了kinect,没有问题;调试的时候在SetMapOutputMode()函数处中断,无法继续。 请问这是怎么一回事呢?

  23. to daisyhaohao 請確認你的 depth generator 是否有建立成功。聽起來應該是根本無法建立 depth generator 所造成的。

  24. 谢谢哦~我调试了很多次没有办法建立depth generator,后来发现是我还有安装微软的kinect SDK,这样的话系统就用默认微软的驱动来识别kinect,所以我再用OpenNI的话就无法读取数据了~后来切换到OpenNI的驱动就好了~哈哈!终于解决!

  25. 您好,又来打扰您了,我把您的文档全下下来了,研究了几天,收益匪潜啊!!!

    回头看这篇,我很好奇
    // 6. Do something with depth map
    这一步到底是怎么弄的?
    const XnDepthPixel* pDepthMap = mDepthGenerator.GetDepthMap();

    我查了OpenNI函数书,看pDepthMap应该不是个矩阵吧?

    请问怎么把pDepthMap转换成图形矩阵?

    或者怎么把图片显示出来?

    望不吝赐教,谢谢

  26. to 林雄民
    pDepthMap 是一個指到該影像陣列第一個元素的指標。
    基本上,C 動態分配出來的陣列,大多都是以這樣的形式做操作。

    如果不習慣使用指標的話,建議可以改用 GetMetaData() 這個形式的函示來做資料的存取。方法請參考:http://viml.nchc.org.tw/blog/paper_info.php?CLASS_ID=1&SUB_ID=1&PAPER_ID=254

  27. 谢谢,我去看看,您的代码是在windows下的,我在linux下测试了,几乎都能通过。

  28. 请问一下版主,我的调试时总是有这个错误
    error C2065: ‘mapMode’ : undeclared identifier
    这个怎么回事?
    :

  29. to euphy

    Heresy 這邊測試是沒有問題的,請檢查你的原始碼是否和範例相同。

  30. 版主我仔细对照了代码没有错误,但是现在debug的时候会有一系列的 Loaded ‘C:\Windows\System32\wintrust.dll’, Cannot find or open the PDB file,这个是怎么回事呀?有什么解决方法呢?急求指教

  31. to euphy

    請確認一下你的問題到底是什麼。
    如果說之前的 error C2065 的話,應該是編譯錯誤,這算是比較嚴重的問題。而這個錯誤訊息,也請確認到底是哪一行產生的。

    後來你所提及的 PDB file 的問題,基本上應該是程式碼已經可以正確編譯了,而在執行階段的DLL 讀取的警告,基本上這個是比較不重要的事、可以無視。

  32. heresy您好:
    請問一下 Kinect 讀出來的深度影像是否為16-bit,
    因為我在網路上看到有說是11,12,14-bit,
    所以感到有些困惑, 來問問高手 ^^
    感謝~

  33. to Mibitri
    他是用 16bit(unsigned short)來儲存的,但是實際上沒有用到全部的 16bit。

  34. 读取深度图后,每次到1,31,61,91,帧的后面
    每过1秒(640*480,30FPS)就出现这个警告一条
    9459013 ERROR Could not open file mapping object (2).
    11319790 ERROR Could not open file mapping object (2).
    12392802 ERROR Could not open file mapping object (2).
    13374745 ERROR Could not open file mapping object (2).

    请问是什么原因,如何消除?
    谢谢~

  35. to gbadown
    請問官方範例也會嗎?
    OpenNI 和 NITE 是否已經更新到最新版本?

  36. to heresy
    nite-win32-1.5.2.21-dev
    openni-win32-1.5.2.23-dev
    SensorKinect-Win32-5.0.0
    NI的两个范例会出现.
    NITE的范例不会。

  37. to gbadown
    建議您也把 SensorKinect 更新到對應的新版本。
    目前應該是使用對應 5.1.0.25 的 0.91

  38. 由于设备自身的限制,深度数据中会有很多无效点,在深度图中就反应为一块块的黑斑。我一直在尝试把这些无效点填充起来,但苦于没有很好的解决办法!请问你能给些建议吗?谢谢!

  39. heresy,你好!
    我想把RGB彩色图、深景图和IR图同时显示出来,但是得到的RGB图却是一片黑!不过,深景图和IR图可以同时显示,深景图和彩色图也可以同时显示,偏偏彩色图和IR图却不能!难道是kinect自身不支持吗?还是其他什么原因?
    万望赐教!

  40. to 小书童
    IR Image 和 RGB Image 是採用同一個感應器,所以無法同時使用。

  41. to 小书童
    沒弄錯的話,他的紅外線影像是去調整 RGB Camera 的 CMOS 來產生的。

  42. heresy大大您好,请问:
    1.
    DepthGenerator的
    GetMetaData() -> DepthMetaData( .Data() )
    GetDepthMap() -> XnDepthPixel
    这两个东西有啥区别?
    2.
    XnDepthPixel(0x0000)大小到底是个啥含义?如果不是所有位都有用,不用的位是有其它含义还是空着的?

  43. to seeyasnow

    1. 不太確認你的問題。
    你是指去呼叫 xn::DepthMetaData::Data() 和呼叫 xn::DepthGenerator::GetDepthMap() 兩者的差異嗎?
    基本上兩者是完全相同的。

    2. 他基本上就是代表深度值,只是目前的設備的深度範圍只有 0-10,000,其他空著的範圍也只會是 0,沒有其他意義。

  44. 谢谢heresy大大,
    那请问1-10000与现实世界的距离有什么对应关系呢?是每一台kinect都一样的吗?
    另外,如果想转成0-255的灰度图,不就是应该drawDepth*255/10000吗?为何我看到有的人做法是*255/2550?

    最后,可有比较好的文档可以推荐看看吗?我也不用老麻烦得问您了。

  45. 谢谢heresy大大,
    那请问1-10000与现实世界的距离有什么对应关系呢?是每一台kinect都一样的吗?
    另外,如果想转成0-255的灰度图,不就是应该drawDepth*255/10000吗?为何我看到有的人做法是*255/2550?

    最后,可有比较好的文档可以推荐看看吗?我也不用老麻烦得问您了。

  46. 谢谢heresy大大,
    那请问1-10000与现实世界的距离有什么对应关系呢?是每一台kinect都一样的吗?
    另外,如果想转成0-255的灰度图,不就是应该drawDepth*255/10000吗?为何我看到有的人做法是*255/2550?

    最后,可有比较好的文档可以推荐看看吗?我也不用老麻烦得问您了。

  47. 谢谢heresy大大,
    那请问1-10000与现实世界的距离有什么对应关系呢?是每一台kinect都一样的吗?
    另外,如果想转成0-255的灰度图,不就是应该drawDepth*255/10000吗?为何我看到有的人做法是*255/2550?

    最后,可有比较好的文档可以推荐看看吗?我也不用老麻烦得问您了。

  48. 谢谢heresy大大,
    那请问1-10000与现实世界的距离有什么对应关系呢?是每一台kinect都一样的吗?
    另外,如果想转成0-255的灰度图,不就是应该drawDepth*255/10000吗?为何我看到有的人做法是*255/2550?

    最后,可有比较好的文档可以推荐看看吗?我也不用老麻烦得问您了。

  49. to seeyasnow
    基本上 0-10,000 是硬體上的值,所以目前每一個裝置應該都是相同的。
    至於轉換的方法,實際上是可以根據使用需求來做調整的;看看你想強化哪一部分的範圍,再根據這個條件來做計算。

    至於資料的部分,其實 OpenNI 本身的文件已經算是相當衝縫了。

  50. 麻烦问一下,要保存kinect获得的坐标数据以方便下次取出使用的话,用Kinect for Windows SDK是不是没办法实现?

  51. heresy 您好,如果我的坐标是想保存成txt格式的在kinect studio是没办法实现是吗?

  52. to henry
    不管是 OpenNI 或 Kinect for Windows SDK,應該都不支援將座標點存成文字檔形式、之後再讀取的功能。
    如果有需要這樣的功能,應該需要自己想辦法實作。

  53. hersey您好,我用的64位win7,按照以前32位上的经验配置好了环境,samples里的例子可以运行,但是自己编译的程序会出现例如unresolved external symbol __imp__xnInit这样的错误,请问是什么原因呢

  54. to JK

    請確定在您的專案設定內,有正確的設定去連結 OpenNI.lib 或是 OpenNI64.lib。
    要使用哪的版本是要看你的程式是要建置成 32 位元或是 64 位元而定。

  55. to hersey

    都链接好了,以前在32位机器上配置过,不知道64位有没有什么需要特别注意的地方?还有您后面说的“程式建置成32位元或是64位元”不是很理解

  56. to hersey
    您好,請問有沒有辦法直接從内部直接讀出骨架(頭手腳)的x,y,z值輸出txt檔?謝謝

  57. to hersey
    請問深度輸出灰階(0~255)有沒有辦法轉換成距離?公式是什麽?謝謝~

  58. 請問我的電腦是64位元,OpenNI安裝的也是64位元
    路徑設定上也有改成OpenNI64.lib
    依照上面所敘述的方式去建置,卻還是出現無法開起來源”XnCppWrapper.h”的原因為何?

  59. @ Michael

    找不到 header 檔通常是 include path 不對的關係。
    請確定你設定的 Additional Include Directories 是正確的。
    如果只有安裝 64 位元版本 OpenNI,需要設定為 $(OPEN_NI_INCLUDE64)

    另外,也請確認你安裝的 OpenNI 版本是 1.x 還是 2.x,兩者是完全不同的。

  60. @heresy

    非常感謝您,這個問題已經解決,不過在我建置時卻又出現
    LNK2019: 無法解析的外部符號 __imp__xnShutdown 在函式 “public: void __thiscall xn::Context::Shutdown(void)” (?Shutdown@Context@xn@@QAEXXZ) 中被參考
    這種錯誤,懇請大神求助

  61. @Michael

    Link Error 大部分是沒有正確指定需要的 lib 檔,或是 lib 指定錯誤造成的。

  62. 你好,刚接触kinect,打算先做静态手势识别,请问一下为什么获取的深度图像中,手部都会有一个“阴影”呢,伸出一根手指,影像中显示为灰色,但是周围还会出现一个黑色的手指。谢谢!

  63. to hualitlc

    那是手指遮擋住深度感應器的影子。
    這是這款深度攝影機技術原理的問題,基本上越近會越明顯。

  64. 谢谢,那这个会影响基于深度阈值的手部的提取吗?另外想问下,基于深度阈值提取采用哪个函数比较好?

  65. to hualitlc

    基本上取決於你去偵測手的方法。
    如果從深度資料上還可以是別出手的外型,基本上就還可以處理。

  66. @heresy
    heresy大大,我是一个初学者,我在vc6.0环境下编写您的代码编译后出现 fatal error C1189: #error : Xiron Platform Abstraction Layer – Win32 – Microsoft Visual Studio versions below 2003 (7.0) are not supported!请问是版本问题吗?

  67. to sdl
    錯誤訊息應該已經算是寫得很明確了。
    他不能在 VisualStudio 2003 前的環境使用。

  68. @heresy
    heresy大大那我该如何修改才能使用呢?环境可以修改吗?还是它就不支持这个版本吗?如果我想用vc 来开发openni的话该用哪个版本的vc 开发软件?谢谢大大

  69. 大大,我想请问一下有没有办法在一个比较复杂的环境下,捕捉到一个运动物体的三维坐标呢,且Kinect是运动的,所以其他景物相对于Kinect也都是运动的。

  70. to 傻傻傻H

    OpenNI 或 Kinect for Windows SDK 本身應該都沒有提供這樣的功能,必須要自己去實作追蹤的演算法。(或是找現成的)

  71. to 大大
    从Kinect2.0的深度数据中可以看出,有很多深度值从0突变为任意值(2000 ,4000 ,7000 等都有)的像素点,从显示的图像上也可以看出有很多黑色白色突变的像素点(也说明深度值在0到一个很大的数值之间突变),请问这是为什么呢?或者该怎么滤除呢??:cry:

  72. to 傻傻傻H

    深度感應器現在的技術在某些情況下,都還是會有偵測不了深度的狀況。
    而如果它的深度值是 0,就代表這一點在當下沒有辦法偵測到深度,之後有值,則是成功偵測到了。

    基本上,這是目前技術上的門檻,短時間應該也無法解決,只能自己看想用哪種方法,把她補起來、或是直接跳過這一點。

Leave a Reply

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *