Virtual Device for OpenNI 2


這是一個 OpenNI 2 用的虛擬裝置模組,他的功能基本上是提供 OpenNI 2 環境建立一個虛擬裝置的功能,讓程式開發者可以自行去指定這個虛擬裝置的資料;比如說,如果是有其他形式的深度影像、或是其他深度攝影機的資料,都可以透過這個模組,來讓資料可以在 OpenNI 2 的架構下來使用。

而另一方面,這也可以用來模擬類似 OpenN1 時提供的「Mock Node」、也就是可以用來修改取得道的深度資料、讓之後的 middleware(PrimeSense NiTE)可以使用。(參考《修改 User Generator 用來分析的深度影像》)

這個模組是以 OpenSource 的形式,放在 GitHub 上,他的網址是:https://github.com/VIML/VirtualDeviceForOpenNI2
另外,雖然這個模組也有以 tools 的形式 submit 給 OpenNI 了,但是看來似乎都沒有被處理。


基本使用

由於這個虛擬裝置模組算是 OpenNI 2 的驅動程式模組的一種(類似之前的 WebCam4OpenNI2),所以如果是要使用現成編譯好的檔案,也只需要下載編譯好的 DLL(VirtualDevice.dll),放到工作目錄下的 \OpenNI2\Drivers 裡面,和 PS1080.dllKinect.dll 等檔案放在一起就可以了。

而要在建立一個虛擬裝置的話,則是要在建立 OpenNI Device 的時候,指定特別的 URI:

\\OpenNI2\\VirtualDevice\\<<STRING>>

其中,<<STRING>> 的部分可以自行更換,只要名字不同,就可以建立不同的裝置。下面就是一個範例:

Device  devVirDevice;
devVirDevice.open( "\\OpenNI2\\VirtualDevice\\TEST" );

而在建立出虛擬裝置 devVirDevice 後,接下來則就是按照標準的作法,建立出需要的 VideoStream、用來讀取資料;目前的版本僅支援彩色和深度兩種 Video Stream,不支援紅外線。

在建立出 VideoStream 的物件後,使用前則需要透過 setVideoMode() 來指定要使用的解析度,這樣 VideoStream 才知道之後要產生多大的畫面。

虛擬裝置的 VideoStream 都準備好了之後,如果要給他新的資料的話,基本上是要先透過 VideoStreaminvoke() 函式、來執行 GET_VIRTUAL_STREAM_IMAGE 這個命令,來要求 VideoStream 配置一個 OniFrame 的物件、讓程式可以填自己的資料進去;而在準備好資料之後,則是再透過 invoke() 執行 SET_VIRTUAL_STREAM_IMAGE 這個命令、把修改好的資料、傳給 VideoStream、告訴他新的畫面已經準備好了。

其中,GET_VIRTUAL_STREAM_IMAGESET_VIRTUAL_STREAM_IMAGE 這兩個特殊命令,則是定義在 VirtualDevice.h 這個檔案(連結)裡;如果要使用的話,可以直接把那兩行定義加到自己的程式碼裡面,或是直接 include 這個 header 檔。

下面就是一段範例:

// get a frame form virtual video stream
OniFrame* pFrame = NULL;
if( pVStream->invoke( GET_VIRTUAL_STREAM_IMAGE, pFrame )==openni::STATUS_OK )
{
  // type casting
  DepthPixel* pVirData = reinterpret_cast<DepthPixel*>( pFrame->data );
 
  // Fill dummy data
  for( int y = 0; y < pFrame->height; ++ y )
  {
    for( int x = 0; x < pFrame->width; ++ x )
    {
      int idx = x + y * pFrame->width;
      pVirData[idx] = 100;
    }
  }
 
  // write data to form virtual video stream
  pVStream->invoke( SET_VIRTUAL_STREAM_IMAGE, pFrame );
}

透過上面這樣的程式,就可以讓 pVStream 這個虛擬的深度影像的 VideoStream 產生一張每一個像素都是 100 的深度影像。

而通常這部分程式,應該是需要另外建立一個新的執行緒來執行的。完整的範例,可以參考 GitHub 上的「BasicSample」這個範例。

不過要注意的是,這邊用的 thread 函式庫是使用 OpenNI 原始碼裡面、XnLib 所提供的功能,所以如果要建置的話,是需要 OpenNI 原始碼的;或者,也可以直接用 C++11 的 Thread,或是其他的執行緒函式庫。


屬性

為了讓這個虛擬裝置可以支援各項屬性,所以在 DeviceVideoStream 裡,都有設計 property pool 的機制,來儲存各種類型的屬性資料。要使用的話,基本上就是透過 OpenNI 提供的各種介面、或是直接使用 setProperty() 來做設定、並透過 getProperty() 來讀取。

不過,除了 ONI_STREAM_PROPERTY_VIDEO_MODEONI_STREAM_PROPERTY_CROPPING 這兩個屬性會動到 VideoStream 的設定外,其他的所有屬性都只是單純地被儲存下來、並不會對虛擬裝置造成任何影響。像是雖然可以透過 setMirroringEnabled() 來設定 ONI_STREAM_PROPERTY_MIRRORING,但是實際上影像並不會因此產生鏡像效果。

另外,如果是深度影像、而且會用到座標系統轉換(Depth / World)的話,則還需要指定 ONI_STREAM_PROPERTY_VERTICAL_FOVONI_STREAM_PROPERTY_HORIZONTAL_FOV 這兩個屬性的值, CoordinateConverter 才有辦法進行座標轉換的計算。


修改現有裝置的影像

如果是需要搭配 OpenNI 現有的感應器、來修改實際感應器讀取到的資料(類似 OpenNI 1 的 mock node)的話,則是可以參考「ExistedDeviceSample」這個範例。

使用方法基本上就是先按照一般的方法,建立出正常的 Device、和需要的 VideoStream;接下來則是建立虛擬的裝置,並透過實際的 VideoStreamaddNewFrameListener()、來讓真實裝置讀取到新的影像後、就把資料做完處理、丟給虛擬裝置用。

這樣處理後,之後就可以透過虛擬的 VideoStream 來讀取修改過的資料了。


給 PrimeSense NiTE 使用

首先要注意的是,雖然 PrimeSense 所提供的 NiTE2 這個 middleware 是可以免費使用的,但是實際上在使用上,他是有一些限制的。其中一個最重要的,就是在它的使用授權裡面、就有明寫、他只能用在「經過授權的硬體」上,而經過授權的硬體,基本上就是採用 PrimeSense 自家感應器的產品(MS Kinect、ASUS Xtion…)了~

c. You shall not (and shall not permit third parties to):

(a) integrate the NITE with any products other than the Authorized Hardware;

(b) distribute the NITE in any manner;

(c) use or make available the NITE pursuant to an open source license;

(d) modify the NITE; or

(e) change, obscure or delete any proprietary notices or legends which appear in the NITE.

You understand and agree that under no circumstances will You (or will You allow distributors, resellers or agents to) distribute stand-alone copies or versions of the NITE.

完整的文件,可以參考:http://www.openni.org/nite-licensing-and-distribution-terms/

所以即使是使用虛擬裝置、也不能在沒有 PrimeSense 感應器的情況下,使用 NiTE。


而如果要是要把 VirtualDevice 拿來當 Mock Node 的形式來使用、也就是用來修改現有感應器的深度資料、給 NiTE 來分析的話,在使用上,也還有幾個要注意的地方。

裝置的 URI

首先,NiTE2 的 UserTrackerHandTracker 物件,在透過 cretae() 指定 Device 來建立的時候,實際上應該是會針對裝置的 URI 作檢查的。不過由於 PrimeSense 並沒有公開他的檢查機制,所以 URI 的部分基本上只能自己測試看看哪種可以通過檢查。

就 Heresy 測試的結果,下面這個 URI 應該是可以通過 NiTE 的檢查的:

\OpenNI2\VirtualDevice\Kinect

所以如果建立的虛擬裝置是要給 NiTE2 用的話,就需要使用這個 URI;至於其他還有沒有可以通過 NiTE 檢查的,可能就要做測試才知道了。

支援的解析度

由於 NiTE 是為了 PrimeSense 自家的感應器所開發的,所以他也只支援自家感應器能提供的解析度。基本上,應該就是 QVGA(320×240)和 VGA(640×480)兩種。所以如果是要搭配 NiTE 來使用的話,也需要使用這兩種解析度才行,其他的解析度是有可能會導致 NiTE 無法成功建立所需要的 tracker 的。

額外的屬性

另外,NiTE 在分析深度影像時,還會再像深度影像的 VideoStream 要求一些特別的屬性資料,包括了:

XN_STREAM_PROPERTY_CONST_SHIFT 
XN_STREAM_PROPERTY_PARAM_COEFF
XN_STREAM_PROPERTY_SHIFT_SCALE
XN_STREAM_PROPERTY_MAX_SHIFT
XN_STREAM_PROPERTY_S2D_TABLE
XN_STREAM_PROPERTY_D2S_TABLE
XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE
XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE
XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE

這些屬性都定義在 PS1080.h 裡面(連結)。

所以如果要給 NiTE 使用的話,在建立出深度的 VideoStream 後,還需要把上面這些屬性、從實際的裝置裡面讀取出來、在設定給虛擬的裝置。

而針對這個需求的處理,Heresy 的做法是這樣:

std::map<int,int>  mapProperties;
mapProperties[XN_STREAM_PROPERTY_CONST_SHIFT]        = 8;
mapProperties[XN_STREAM_PROPERTY_PARAM_COEFF]        = 8;
mapProperties[XN_STREAM_PROPERTY_SHIFT_SCALE]        = 8;
mapProperties[XN_STREAM_PROPERTY_MAX_SHIFT]          = 8;
mapProperties[XN_STREAM_PROPERTY_S2D_TABLE]          = 4096;
mapProperties[XN_STREAM_PROPERTY_D2S_TABLE]          = 20002;
mapProperties[XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE]    = 8;
mapProperties[XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE]    = 8;
mapProperties[XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE]  = 8;

for( auto itProp = mapProperties.begin();
     itProp != mapProperties.end(); ++ itProp )
{
  int iSize = itProp->second;
  char* pData = new char[itProp->second];
  rStream.getProperty( itProp->first, pData, &iSize );
  pStream->setProperty( itProp->first, pData, iSize );
  delete [] pData;
}

其中,rStream 是真正的感應器的 VideoStream、而 pStream 則是虛擬感應器的 VideoStream。這樣的做法,就是先把需要的屬性、以及該屬性的資料大小,都先定義在 mapProperties 裡面,然後再透過迴圈、一個一個從 rStream 裡讀出來、並儲存到 pStream 裡。`

完整的範例,可以參考「NiTESample」這個範例程式。在這個範例程式裡面,Heresy 是建立了一個名為 VirtualDeviceHelper.h 的檔案,裡面提供了一個 CreateVirtualStream() 的函式,可以用來快速地根據現有的 VideoStream、建立出一個 NiTE 可以使用的虛擬 VideoStream。他的介面如下:

openni::VideoStream* CreateVirtualStream( openni::Device& rVDevice,
                                          openni::VideoStream& rStream,
                                          CFrameModifer::TCallback func )

其中,第一個參數的 vDevice 是虛擬的 Device,而第二個 rStream 則是用來做參考的實際 VideoStream;最後的 func 則是一個 function object,用來指定當 rStream 取得到新畫面後、要做那些事;他的介面是:

std::function<void(const OniFrame&,OniFrame&)>

第一個參數是讀取到的新畫面、第二個參數則是要送給虛擬 VideoStream 的畫面。

完整的使用範例,就請參考範例程式了。


這篇介紹就寫到這了。基本上,這東西算是一個比較進階的東西,他主要的功能,就是產生一個虛擬的 OpenNI Device,接下來要怎麼應用,就看自己了~

而目前 Heresy 自己是測試過,可以把它和 PrimeSense NiTE 2 合併使用,不過其他的 middleware library 的話,Heresy 就沒有試過了。理論上,如果可以指定要用哪個 Device、或是指定要用哪個 VideoStream 的話,應該是要可以用才對的。


OpenNI / Kinect 相關文章目錄

對「Virtual Device for OpenNI 2」的想法

  1. Heresy,请问我使用virtual device修改现有装置的资料时修改不了,ExistedDeviceSample可以运行,但无论怎么修改"pVirData[idx] = “等号后面的内容输出结果都是我的实际设备Xtion2的感应数据。另外在执行NITESample时,发现同样无法改动实际设备的数据,请问这个问题该如何解决。我的电脑是core i5-8265U 1.6-1.8Hz,RAM 8G,64bit windows10 的

    • 目前可以确认是在原代码的第38行 if( m_rVStream.invoke( GET_VIRTUAL_STREAM_IMAGE, pFrame ) == openni::STATUS_OK ) 这里失败了,但为什么失败还是搞不清楚

      • 建議請先確認他的錯誤到底是什麼再發問。
        他的回傳值,還有螢幕上顯示的內容都是有意義的。

        • Heresy,你好,在ExistedDeviceSample的class CFrameModifer的protected的 CFrameModifer& operator=(const CFrameModifer&);这里operator下面有个绿色波浪线提示"未找到"operator="的函数定义",但程式还是可以执行,不知道这个问题是否可以忽略

          • 你講的應該是 Visual Studio 的 vs intellisense 的警告,只要能正確編譯,基本上不會有問題。

        • Heresy,我改运行BasicSample发现不能修改深度信息的问题仍然存在,device.open给定的"\\OpenNI2\\VirtualDevice\\TEST"实际上开启的还是真实设备。对这个问题我有两个猜测,一个是不是与使用的真实设备有关,我用的是Xtion2,如果用kinect这个问题会不会解决。第二个猜测是与VirtualDevice.dll有关,我看VirtualDevice.cpp里有 “XnLib.h"这个头文件,而我的openni include里面没有,不知道是不是这个原因。
          另外关于XnLib.h,在你的其他回答里说是openni的source code,这里指的是openni一代吗?不过我在一代的include文件夹里也没找到,但在二代的某个文件夹里找到了同名文件不知是否正确(见https://github.com/OpenNI/OpenNI2/tree/master/ThirdParty/PSCommon/XnLib/Include )

          • 进一步调试,在主程序添加如下代码
            if (vsVirDepth.isCommandSupported(GET_VIRTUAL_STREAM_IMAGE) != 1)
            {
            cerr << "Can't GET_VIRTUAL_STREAM_IMAGE " << OpenNI::getExtendedError() << endl;
            return -1;
            }

            if (vsVirDepth.isCommandSupported(SET_VIRTUAL_STREAM_IMAGE) != 1)
            {
            cerr << "Can't SET_VIRTUAL_STREAM_IMAGE " << OpenNI::getExtendedError() << endl;
            return -1;
            }
            果然报错,似乎是GET_VIRTUAL_STREAM_IMAGE和SET_VIRTUAL_STREAM_IMAGE的数字对应的命令不支持的缘故

          • 對,文章中就有提到了,XnLib.h 是從 OpenNI 的原始碼中取得的了。
            如果不想用,就自己換成別的 thread 函式庫。

        • 当前发现不管Drivers下面有没有VirtualDevice.dll,也不管URI填写的是什么字符串,打开的设备都是我 的真实设备。不知道是不是Xtion2设备的原因或者是从Asus下载的openni2.2的原因

          • 1. BasicSample 並不需要實體裝置,建議你先把實體裝質疑除試試看。
            2. 如果要排除 Xtion2 的模組的影響,也可以暫時先將他所提供的 dll 移除(RvcLib.dll 和 SenDuck.dll)(https://kheresy.wordpress.com/2017/06/17/asus-xtion-2-usage/)

    • 请问另一个问题,在使用NITESample原代码时提示"Can’t create user tracker"。我改为直接执行mUserTracker.create(&virDevice); 提示NiTE2处引发的异常,0xC0000005读取位置0x0000000000000000时发生访问冲突。问题定位于NiTE.h的
      Status readFrame(UserTrackerFrameRef* pFrame)
      {
      NiteUserTrackerFrame *pNiteFrame = NULL;
      Status rc = (Status)niteReadUserTrackerFrame(m_userTrackerHandle, &pNiteFrame); //877行这里
      pFrame->setReference(m_userTrackerHandle, pNiteFrame);

      return rc;
      }

      这种问题该如何解决

      • 個人建議,請按部就班,確定 BasicSample 可以正確運作在往下一步測試。
        你基礎的範例都無法執行了,更進一步的當然不能跑啊。

  2. Heresy您好, 想請教您 我有參考 WebCam4OpenNI2 這篇,如果利用雙鏡頭的硬體設備,採用opencv 的一些演算法來產生景深圖,是否能應用到Virtual device的景深圖來源呢? 謝謝您

  3. heresy,十分感谢你的分享。我的有一个需求,希望通过nite自带的userTracker分割出人体同时提取骨架,但是数据源是离线采集号的一连串图片(下载自公开的RGB-D数据集)。是不是可以通过建立一个虚拟设备,将离线的数据复制到在线连接着的xtion上,来实现?如果可以,怎样才能从离线的图片建立一个视频流?

    • 請自行參考 NiTESample 這個範例,然後在 CreateVirtualStream() 時,設定填入資料的方法。

      不過:
      1. 這樣的作法應該也算是違反授權的
      2. 感應器參數差太多應該也會有問題

      • 之前有前辈提起说用Kinect SDK,那请问使用Kinect SDK是否能实现离线我的需求呢,对离线图像进行用户分割和骨架提取?是否有可以参考的程式?

        • 不太可能。
          Kinect for Windows SDK 沒有提供類似的方法可介入,也不是開放原始碼的方案,有東西可以參考,基本上很難做到。

          • heresy, 你好。我尝试在Ubuntu下运行VirtualDevice的范例,因为github上只提供了windows的工程,所以我自己写了cmakelists,配置好了相关环境,如OpenNI的源码等,然后将VirtualDevice.cpp包含进范例(如ExistedDeviceSample或NiteSample),编译通过。但是均无法成功打开虚拟设备。
            提示为:Can’t create virtual device: DeviceOpen: Couldn’t open device ‘\OpenNI2\VirtualDevice\TEST’

            是否因为我没有自己编译一个VirtualDevice.so然后放到Driver下面?

          • Hi, Heresy。我生成了shared library然后放到/OpenNI-Linux-x64-2.2/Tools/OpenNI2/Drivers目录下了,但仍没有解决问题,依旧会提示无法打开虚拟设备。

        • 抱歉,由於 Heresy 沒在 Linux 環境測試過,不確定狀況。
          不過,請確認你是把建置出來的檔案,放在執行檔所在路徑下的「OpenNI2/Drivers」的資料夾中。

          • Hi,Heresy。我找到问题了,因为我在生成分享库的时候没有设置为release,生成release库后就能否跑虚拟设备了,感谢Heresy!

  4. 你好,Heresy:
    我用Openni2.1写了一个双目摄像头的驱动,能够得到深度信息。现在想结合NiTE2得到骨骼信息。直接传深度流好像这NiTE.dll里面会报错。看到你用虚拟驱动的Mock Node能够实现将流传给NiTE2使用。我去GITHUb上看了你写的虚拟驱动 好像用的Openni2.2 版本。Openni2.2 版本和Openni2.1 版本库里面有些函数不一样,比如说Openni2.1 版本里面用的对象是OniDriverFrame 但是Openni2.2 版本却是OniFrame.请问,我自己改了一下发现invoke里面报错了。你有Openni2.1 版本的虚拟驱动程序么?谢谢。

    • 1. 個人建議你直接升級到 OpenNI 2.2
      2. Heresy 這個專案是從 OpenNI 2.2 開始寫的,所以沒有 2.1 的版本。
      3. 你自己寫驅動程式模組給 NiTE 用,基本上一定會出錯,本文中「給 PrimeSense NiTE 使用」這一段已經有說明原因了。

      最後,你搭配非 PrimeSense 的感應器使用 NiTE 是違反授權協議的。

      • 您好,
        您这文中写到的创建一个虛擬的 OpenNI Device可以和 PrimeSense NiTE 2 合併使用。那我能使用虚拟驱动的Mock Node 的方式给nite做分析么?我看了您在github上niteSample的例子。我创建的实际驱动的深度流是双目摄像头的,然后传递给虚拟驱动的深度流,再给nite分析应该是可行的吧。
        还有个问题就是我把驱动改到openni2,2版本后,调用的时候在class MyDriver : public oni::driver::DriverBase里面的构造函数和 initialize函数都不可以。同样的模式我在2.1版本里面是可以的呢。Openni2.2跟2.1在调用上有很大的区别么?谢谢。

      • 您好,
        我在运行您的nite sample的时候在 mUserTracker.create( &virDevice ) != STATUS_OK的时候z 在nite.dll里面报错了。我用的是kinect+virtualDevice两个dll以及NiTE2.0是因为我选择的版本不对么?

      • OpenNI 2.1 和 OpenNI 2.2 在驅動程式模組方面的差異,建議請直接參考官方的原始碼;根據兩個版本的程式碼不同,應該可以看的出來。
        或者,之前 Heresy 另外寫的 WebCam4OpenNI2( https://kheresy.wordpress.com/2013/04/29/webcam4openni2/ ),就有跨 OpenNI 2.1 和 2.2 的部分,應該也可以作為參考: https://github.com/KHeresy/WebCam4OpenNI2/commit/8c442077499f73fac6f452c6e00a9c0c11e769ef

        再來,麻煩請把本文中「給 PrimeSense NiTE 使用」這段落認真看完,裡面有寫要給 NiTE 用有哪些限制。
        而要執行所提供的範例的時候,請確認你有接上 PrimeSense 的感應器,例如 ASUS Xtion 或第一代的 Kinect,否則還是不能用的;原因就是他沒有那些必要的「額外屬性」資料。

        • 谢谢您的回复。我在运行gitHub上nite sample的时候用的就是kinect一代。去掉虚拟驱动部分的代码可以正常运行显示骨骼信息,但是加了虚拟驱动的代码以后会在
          UserTracker mUserTracker;
          if( mUserTracker.create( &virDevice ) != STATUS_OK )
          {
          cerr << "Can't create user tracker" << endl;
          return -1;
          }
          中的if语句就报错。错误是:在nite2.dll中有未经处理的异常,integer devision by zero.然后在代码并没有做除以0的操作。其中我的openni版本是2.2 nite版本是2.0 .

      • 您好,
        我自己写的驱动程序模组打包成dll放到OpenNI2/Drivers 下面我使用彩色信息流的时候可以正常读取到摄像头的图像(彩色流模仿您webcamera4opencv的),但是读取深度流的时候就报下面的错误(两者的dll是用的同一个)。驱动里彩色流和深度流创建的Device类和Driver类讲道理应该是公用的呀。下面的是我的错误信息。
        错误信息为:
        initialize context error: libraryhandler could not load library MyDevice.dll
        DeviceDriver: library handle is invaild for file MyDevice.dll
        could not understand file MyDevice.dll as a device driver
        Found no vaild drivers in “C:\Users\zjh\Documents\Visual Studio 2013\Projects\OpenNI2OpenCVCamera\x64\Release\OpenNI2\Drivers"
        不知道您有没有遇到过这个情况。

          • 您好,
            又来麻烦您了,我把 VirtualDevice 拿來當 Mock Node 的形式來使用,rStream使用的是自己的驱动(驱动可以正常读取深度信息),VirtualDevice 使用的是您Github分享的。然后传递给nite分析。出现错误:Couldn’t get depth2Depth table. 这个错误好像是在nite2里面的,我使用的OpenNI是2.2, NiTE2也是2.2. 同一个代码您GitHub上的NiTESample可以正常运行。是不是我缺少什么东西了?

          • 您好,
            摄像头装置我用的是一个双目摄像头(非红外)。虚拟驱动用的是您分享的VirtualDevice。在CreateVirtualStream函数里面的setProperty均能读取到我自己在驱动程序设定的参数。我观察了OpenNI里面kinect的驱动程序里面有D2S.h.h和S2D.h.h。depth2Depth table与这些有联系么?

        • 文章中已經有說過了,NiTE 還需要從裝置裡面讀取許多特殊的參數,才能使用。
          你在沒有提供這些資料的情況下,他就是會出現類似的錯誤、無法使用。

          VirtualDevice 之所以可以搭配 NiTE 使用,是因為有把這些參數從實際的裝置讀出來,然後儲存在虛擬裝置裡面。
          你自己的攝影機如果沒辦法提供對應、正確的資料,自然是無法使用的。

          麻煩把這篇文章認真看完吧…

          另外,這邊的話題已經變成是在詢問如何破解 NiTE 了,由於這違反了 PrimeSense 的使用授權,將不再針對此話題做回應。

          • 您好,
            我本身没有打算去破解 NiTE的意思。只是看了虚拟驱动之后。只是想尝试自己想法的可行性而已,并没有故意冒犯nite。您在上文中说的從裝置裡面讀取許多特殊的參數就是指XN_STREAM_PROPERTY_CONST_SHIFT
            XN_STREAM_PROPERTY_PARAM_COEFF
            XN_STREAM_PROPERTY_SHIFT_SCALE
            XN_STREAM_PROPERTY_MAX_SHIFT
            XN_STREAM_PROPERTY_S2D_TABLE
            XN_STREAM_PROPERTY_D2S_TABLE
            XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE
            XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE
            XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE
            这九个参数么?还是除了这几个参数之外还需要摄像头内部自己提供参数。
            如果是这九个参数的话您写的虚拟驱动里面是有设置好的,而且我也能从实际的摄像头驱动中读取到这些值并且传递给虚拟驱动的。
            我也是刚接触这个,希望老师您能够指导下。跪谢。

  5. 您好,
    有问题想请问~
    NiTE中的userTracker使用上没有问题,可是handTracker下不能使用,请问需要做什么方面的修改吗?
    谢谢 ~

    • 您好,
      还有另外一个问题想请教,用的时候另外一physical devide的stream会慢然后也会整个卡着这样,请问是正常的吗?谢谢

    • 基本上應該可以用,使用方法和 UserTracker 一樣。

      至於你說會卡著?不知道是什麼狀況,不過這邊會建議不要用 debug、而用 release 模式跑跑看。
      另外,也請試著簡化 VirtualDevice 的資料處理試試看。

  6. 您好,謝謝你之前回我信,對我幫助很大.現在我執行NiTESample時,在
    Status rc = (Status)oniDeviceCreateStream(device._getHandle(), (OniSensorType)sensorType, &streamHandle);
    出現錯誤,而在Create virtual device 時也出現(ERROR) Could not find device \OpenNI2\VirtualDevice\Kinect。是因為這樣才出現那個錯誤嗎? 我的開發環境是Mac OS X.我已經能執行NiTE骨骼偵測的範例,所以應該不是環境設置上的問題.

    就差這一步就能將處理完後的depth data 丟給NiTE處理,但不知道現在的問題是在哪裡。

    謝謝你的幫忙 :)

    • 另外,我是自己利用xcode compile 出virtualdevice.dylib,之後再加進現在的project,是否有可能是我compile dynamic library時出錯而導致的?但我在compile dylib時沒有出現錯誤

      • 抱歉,Heresy 沒用 Mac,不以不確定狀況。
        不過,在 Windows 下,編譯好的 DLL(VirtualDevice.dll)是需要放到工作目錄下的 \OpenNI2\Drivers 目錄裡的;在該資料夾裡面應該也會有 PS1080.dll、Kinect.dll 等檔案。

        • 請問在NiTE Sample裡,哪裡會使用到VirtualDevice.dll? 因為只要include VirtualDeviceHelper.h 之後就能編譯成功,要如何測試VirtualDevice動態程式庫有順利加進project?

          謝謝您

          • 您好,
            在程式裡面是看不出來的,在專案中也不需要做設定。
            OpenNI 他自己會去掃描執行路徑下的 \OpenNI2\Drivers 的資料夾,把所有 dll 當作驅動程式模組讀取。

          • 謝謝您的回覆,發現我沒在Xcode Building Phase 中設定好VirtualDevice.dylib,設定好後NiTE Sample就能正確執行了.另外有個問題想請問您,有辦法是直接create openni VirtualDevice然後給NiTE資料嗎?也就是自己create depth data 而不是從一個OpenNi-Compatible device中讀取

      • 文章中已經有提及了,PrimeSense NiTE 的授權協議不允許你在不使用其感應器的情況下,使用 NiTE。
        這部分不是技術問題,而是授權問題。

        • 您好,若應用在學術研究上應該就沒有授權協議上的問題? 目前是希望能把深度影像經過新的演算法後,交由NiTE去辨識骨骼資訊,並與沒有經過處理的原始深度資訊結果做比較.

          想請問有可能結合Basic Sample NiTE Smaple, 自己創建虛擬device以及深度影像,然後將VideoStream 交給另一個virtual device 給 NiTE 做處理嗎?

          謝謝您的幫忙

          • NiTE 的授權協議對於裝置的限制,並沒有把學術研究排除在外,所以應該還是有同樣的限制;並不是打著學術研究就可以什麼都不管的。
            針對這個需求,簡單講就是:技術上不是問題,問題是法律層面的事…
            當然,把 PrimeSesne 買下來的 Apple 會不會在乎這件事沒人知道。

            你如果只是要測試,最簡單的方法,就是還是接著 PrimeSense 的裝置,然後把整個深度圖全部換掉。

  7. @Heresy,

    非常感谢您的文档,我正好需要一个虚拟设备,在offline的情况下处理获得的深度和色彩数据,通过您提供的代码,我感觉这个功能可以完成。

    另外,我还有一个问题,希望您能给予建议。OpenNI2在捕获数据并且启动IMAGE_REGISTRATION_DEPTH_TO_COLOR这个模式的时候,深度数据比没有注册的情况下要小,恢复出的point cloud也要小一些,而且应该不是linear scale。但是不采用这种模式,调用函数convertDepthToColor无法得到正确的深度和颜色对应结果。不知道您有什么方法可以既保证深度数据不被缩小, 同时能够让深度与色彩数据进行正确匹配,即使得到近似的结果也行?

    十分感谢

    shawn

      • 多谢Heresy! 现在还有一个问题想麻烦你,我使用了virtual device的支持库,但是如果要把virtual device及其VideoStream的对象的声明和使用分开到两个函数中,就必须以指针形式声明virtual device和它的VideoStream。不过在使用 new VideoStream之后,在其他函数中访问和释放时,VideoStream中的OniStreamHandle m_stream参数指针确实存在,但无法访问,获取如同vertical FOV等参数时会出错。不知道你是否遇到这种情况?谢谢!

        • 不好意思,问题已经解决,发现在virtual device声明过程中只使用了临时对象,所以出了问题。谢谢!

          • Shawn, 请问你现在实现了离线数据建立虚拟设备了吗?我也有相同的需求,希望用公开的RGB-D数据集的离线图片跑NITE的userTracker,但我不知道如何将离线图片建立视频流,能否赐教?十分感谢~如果可以,我们可以邮件交流~

發表留言

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料