Kinect SDK v2預覽版,獲取數據的基本流程的說明。以及取得Color圖像的示例程序的介紹。
上一節,是關於當前型號Kinect for Windows(后面稱作Kinect v1)和次世代型的Kinect for Windows的開發者預覽版
(后面稱作Kinect v2
預覽版
)的配置比較和介紹。
從這一節開始,
是Kinect的各種數據的取得方法的比較和介紹。
Color Camera
Kinect和通常的Web攝像頭一樣,
搭載了 Color Camera,
可以取得Color圖像。關於Camera,
Kinect v1的分辨率是
640×480,
Kinect v2
分辨率大幅提升到
1920×1080。這次,
要介紹從Color Camer取得圖像的方法。
數據取得的流程
Kinect SDK v1和Kinect SDK v2
預覽版取得數據的基本流程。
這里表示的是最基礎的流程,
在
Kinect SDK 在v2
預覽版里,
有把多個
「Source」「Reader」一齊處理的API,
和這里介紹的數據獲取的流程也會有差異。

圖1是Kinect SDK v1和Kinect SDK v2預覽版的數據取得流程
Kinect SDK v1,是從「Sensor」打開「Stream」,從「Stream」取得「Frame」,從「Frame」取得數據這樣的流程。
到了
Kinect SDK v2
預覽版,
是
從「Sensor」取得「Source」,
從「Source」打開「Reader」,
從「Reader」取得「Frame」,
從「Frame」取得數據這樣的流程。
每個Kinect SDK v2預覽版的「Source」,都有一個從Kinect取得Color和Depth的1個數據流,這點和
Kinect SDK v1的「Stream」是一樣的。
Kinect SDK v2預覽版,追加了
「Reader」的階段。
「Reader」能打開1個
「Source」多次。通過這個配置,
多線程的應用上,不需要
把取得的數據拷貝到其他線程處理。也有多個應用可以從同一個傳感器取得數據的優點。
(注:因為Color Camera和Depth Camera是分離的,所以Color、Depth和Skeleton數據流也是各自獨立的,API通過Event來通知App是否有數據更新。通常為了效率,對每一個數據流都使用單獨的線程來等待Event,然后處理數據。在之前的v1中,Frame是獨立的,取出后數據就被Drop掉了,所以想在Depth里讀取Color之類的操作,必須使用內存拷貝,而多線程讀寫數據又會需要互斥鎖,十分影響效率;還有一個辦法是通過NuiSetFrameEndEvent,也就是c#接口中的AllFrameReady事件,但是這樣等待所有數據不僅太局限而且效率很低。
)
示例程序
Kinect SDK v2預覽版取得Color畫像的示例程序的展示,圖1展示的是數據取得階段的摘錄解說。這個示例程序的全部內容,在下面的github里公開了。
這個示例程序為了處理圖像數據,使用了
OpenCV。
OpenCV的詳細內容可以參考下面的信息。
「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」。
從「Sensor」取得「Source」。
-
// Source IColorFrameSource* pColorSource; ……1 hResult = pSensor->get_ColorFrameSource( &pColorSource ); ……2 if( FAILED( hResult ) ){ std::cerr << "Error : IKinectSensor::get_ColorFrameSource()" << std::endl; return -1; }
列表1.2 相當於圖1「Source」的部分1 獲取Color Frame的Source接口。2 從Sensor取得 Source。
「Reader」
「Source」從打開「Reader」。
-
// Reader IColorFrameReader* pColorReader; ……1 hResult = pColorSource->OpenReader( &pColorReader ); ……2 if( FAILED( hResult ) ){ std::cerr << "Error : IColorFrameSource::OpenReader()" << std::endl; return -1; }
列表1.3 相當於圖1「Reader」的部分1 獲取Color Frame的Reader接口。2 從Source打開Reader。
「Frame」~「Data」
從「Reader」取得最新的「Frame」。
-
int width = 1920; ……1 int height = 1080; ……1 unsigned int bufferSize = width * height * 4 * sizeof( unsigned char ); ……2 cv::Mat bufferMat( height, width, CV_8UC4 ); ……3 cv::Mat colorMat( height / 2, width / 2, CV_8UC4 ); ……3 cv::namedWindow( "Color" ); while( 1 ){ // Frame IColorFrame* pColorFrame=nullptr; ……4 hResult=pColorReader->AcquireLatestFrame( &pColorFrame ); ……5 if( SUCCEEDED( hResult ) ){ hResult = pColorFrame->CopyConvertedFrameDataToArray( bufferSize, reinterpret_cast<BYTE*>( bufferMat.data ), ColorImageFormat_Bgra ); ……6 if( SUCCEEDED( hResult ) ){ cv::resize( bufferMat, colorMat, cv::Size(), 0.5, 0.5 ); ……7 } } SafeRelease( pColorFrame ); // Show Window cv::imshow( "Color", colorMat ); if( cv::waitKey( 30 ) == VK_ESCAPE ){ break; } }
列表1.4 相當於圖1「Frame」,「Data」的部分1 Color圖像的尺寸(1920×1080)。這里為了簡化說明,畫像尺寸用硬編碼來設定,示例程序可以從Source取得着Frame信息。2 Color圖像的數據尺寸。3 為了處理Color圖像,准備OpenCV的cv::Mat。「bufferMat」是原始的圖像數據,「colorMat」是Resize圖像數據的處理。「CV_8UC4」,是無符號8bit整數(8U),4個channel(C4)並列來表現1個像素的數據格式。4 取得Color圖像的Frame接口。5 從Reader取得最新的Frame。6 從Frame取得Color圖像。默認的格式是YUY2(亮度與色差表現的格式),不過可以經過簡單處理變換為BGRA。7 縮小為長寬各一半的尺寸(960×540)。
從「Frame」取得Color圖像的數據時,
Kinect SDK v1是預先指定圖像尺寸和格式,Kinect SDK v2不能指定圖像尺寸。因此,取得數據后可以按任意形狀來整理。
取出的Color圖像直接顯示
的話尺寸太大(1920×1080),
在這里采用了
OpenCV的resize命令
(cv::resize()),
縮小為長寬各一半的尺寸
(960×540)。(注:閱讀理解時不要受這一段縮放代碼的干擾,
僅僅就是為了考慮在顯示器上顯示的方便觀察,
沒別的意義。)
取出的
Color圖像的數據如果指定的是BGRA格式,
就會像圖2一樣的排列着。藍
(B),
綠(G),
紅(R),
和無效值(A)的共計32bit構成1像素。

圖2 Color圖像的數據排列
運行結果
運行這個示例程序的話,就會像圖3那樣,顯示從Kinect v2預覽版中取得的Color圖像。

總結
本節介紹了從
Kinect SDK v2
預覽版中取得數據的基本流程和取得Color圖像的示例程序,
下一節將介紹取得Depth數據的示例程序。