Kinect SDK v2預覽版,取得Depth數據的方法說明。
上一節,介紹了
通過使用
Kinect for Windows SDK v2
預覽版
(以下簡稱為,
Kinect SDK v2
預覽版)
從
Kinect for Windows v2
開發者預覽版(后面稱,
Kinect v2
預覽版)取得Color的方法。
這一節,介紹的是從Kinect取得Depth數據的方法。
Depth傳感器
Kinect搭載Depth傳感器,可以取得Depth數據(和傳感器的距離信息)。
Kinect v1,
可以讀取投射的紅外線pattern,
從pattern
的變形獲取Depth的信息,
搭載了「Light Coding」方式的Depth傳感器。
Kinect v2預覽版,通過從投射的紅外線脈沖反射回來的時間來獲得Depth的信息,變更為「Time of Flight(ToF)」方式的Depth傳感器。
「Light Coding」是以色列
PrimeSense公司的Depth傳感技術。詳細請參照專利信息,
美國申請專利公開(US 2010/0118123 A1)- Depth Mapping using Projected Patterns。
「Time of Flight(ToF)」是美國微軟公司收購的擁有Time of Flight(ToF)方式的Depth傳感技術的公司(3DV Systems公司,Canesta公司),一般認為使用的是這個技術。
Depth數據的分辨率,
Kinect v1是320×240,
不過,
Kinect v2
預覽版提升為512×424。另外,
深度方向的分辨率也提高了。
可以
取得
Depth
的
數據范圍
,
Kinect v1是0.8~4.0[m]的范圍
,
Kinect
v2
預覽版可以取得0.5~4.5[m]的范圍。
上面說的是Default Mode的Depth數據范圍。
Kinect v1提供了取得近距離的Depth數據的
Near Mode(0.4~3.0[m])和取得遠距離Depth數據的
Extended Depth(~約10.0[m])。但是,
偏離
Default Mode的范圍的
Depth數據的精度會下降。
這節,介紹從Depth傳感器取得Depth數據的方法。

圖1「Light Coding」方式和「Time of Flight(ToF)」方式的差異(Depth傳感器的工作原理的圖像)
示例程序
Kinect SDK v2
預覽版取得Depth數據,
可視化展示
的示例程序。上一節的介紹的數據取得階段的摘錄解說。這個示例程序的全部內容,
在下面的github里全部公開了。

圖2 Kinect SDK v2預覽版的數據取得流程(重發)
「Sensor」
取得「Sensor」
// Sensor IKinectSensor* pSensor; ……1 HRESULT hResult = S_OK; hResult = GetDefaultKinectSensor( &pSensor ); ……2 if( FAILED( hResult ) ){ std::cerr << "Error : GetDefaultKinectSensor" << std::endl; return -1; } hResult = pSensor->Open(); ……3 if( FAILED( hResult ) ){ std::cerr << "Error : IKinectSensor::Open()" << std::endl; return -1; }
列表1.1 相當於圖1「Sensor」的部分(重發)
1 處理Kinect v2預覽版的Sensor接口。
2 取得默認的
Sensor。
3 打開Sensor。
「Source」
從「Sensor」取得「Source」。
// Source IDepthFrameSource* pDepthSource; ……1 hResult = pSensor->get_DepthFrameSource( &pDepthSource ); ……2 if( FAILED( hResult ) ){ std::cerr << "Error : IKinectSensor::get_DepthFrameSource()" << std::endl; return -1; }
列表1.2
相當於圖1「Source」的部分
1 取得Depth Frame的Source接口。
2 從Sensor取得
Source。
Kinect SDK v1,
要取得
Depth數據主要是利用可以同時取得的
Depth和
Player(人體區域
)的「Stream」。因此,
必須要有Depth數據和Player數據的分割處理。(注:
Kinect SDK v1提供2種方式來處理Depth和Player Index,老的方法返回一組USHORT,通過位移分離兩者;新的方法返回各為2個USHORT的結構
)
Kinect SDK v2預覽版,Depth和BodyIndex(相當於Kinect SDK v1的Player)分別作為「Source」取得,關於BodyIndex在下一節介紹。
Kinect SDK v1也准備了取得Depth的「Stream」,因為獲取Player和Skeleton(人體姿勢)數據的情況也很多,主要可以同時取得Depth和Player的「Stream」。
「Reader」
「Source」從打開「Reader」。
// Reader IDepthFrameReader* pDepthReader; ……1 hResult = pDepthSource->OpenReader( &pDepthReader ); ……2 if( FAILED( hResult ) ){ std::cerr << "Error : IDepthFrameSource::OpenReader()" << std::endl; return -1; }
列表1.3 相當於圖1「Reader」的部分
1 取得Depth Frame的Reader接口。
2 從Source打開Reader。
「Frame」~「Data」
從「Reader」取得最新的「Frame」。
int width = 512; ……1 int height = 424; ……1 unsigned int bufferSize = width * height * sizeof( unsigned short ); ……2 cv::Mat bufferMat( height, width, CV_16SC1 ); ……3 cv::Mat depthMat( height, width, CV_8UC1 ); ……3 cv::namedWindow( "Depth" ); while( 1 ){ // Frame IDepthFrame* pDepthFrame = nullptr; ……4 hResult = pDepthReader->AcquireLatestFrame( &pDepthFrame ); ……5 if( SUCCEEDED( hResult ) ){ hResult = pDepthFrame->AccessUnderlyingBuffer( &bufferSize, reinterpret_cast<UINT16**>( &bufferMat.data ) ); ……6 if( SUCCEEDED( hResult ) ){ bufferMat.convertTo( depthMat, CV_8U, -255.0f / 4500.0f, 255.0f ); ……7 } } SafeRelease( pDepthFrame ); // Show Window cv::imshow( "Depth", depthMat ); if( cv::waitKey( 30 ) == VK_ESCAPE ){ break; } }
列表1.4 相當於圖1「Frame」,「Data」的部分
1 Depth數據的尺寸(512×424)。
這里為了簡化說明,畫像尺寸用硬代碼來設定,示例程序可以Source取得着Frame信息。
2 Depth數據的尺寸。
3 為了處理Depth數據而准備的OpenCV的cv::Mat類型。
「bufferMat」是16bit的原始的Depth數據,「depthMat」為了作為圖像顯示,把Depth數據儲存到8bit的范圍里的處理。
「CV_16SC1」,是把無符號16bit整數(16S) 放入1個channel(C1)並列來表現1個像素的數據格式。(注:應該是CV_16UC1才對)
「CV_8UC1」,是表現無符號8bit整數 (8U)的數據格式。
4 取得Depth數據的Frame接口。
5 從Reader取得最新的Frame。
6 從Frame取得Depth數據。
取得Depth數據存儲數組的指針。這里為了
Depth數據可視化,方便變化處理,用cv::Mat類型來獲取。
7 為了
顯示Depth數據圖像,從16bit轉換為8bit。
如果得到「Frame」,
就可以把取出Depth數據,
作成圖像來可視化。
取出的Depth數據,
像圖3一樣以16bit(0~4500)為1像素來構成。
因為這樣的圖像不能顯示(注:OpenCV只能顯示8bit的圖像數據),需要
把格式轉化為8bit(0~255)的范圍。示例程序,
使用cv::Mat的轉換命令(cv::Mat::convertTo())把離傳感器距離近的顯示很白(255),
遠的顯示為很黑(0)的方式來轉化。

圖3 Depth數據的排列
運行結果
運行這個示例程序的話,在
Kinect v2
預覽版取得深度圖像,
就像圖4一樣。

圖4 運行結果
總結
本節介紹了通過
Kinect SDK v2
預覽版取得Depth數據的示例程序。下一節介紹取得B
odyIndex數據的示例程序。