Kinect学习(五):提取带用户ID的深度数据
生活随笔
收集整理的這篇文章主要介紹了
Kinect学习(五):提取带用户ID的深度数据
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
前言
在前面的一篇文章中討論了如何從Kinect獲取深度圖:Kinect學習(四):提取深度數據。
這里要對其進行拓展,Kinect可以獲取兩種格式的深度圖:
在前一篇文章(Kinect學習(四):提取深度數據)中是使用的就是前者,這里要使用后者。通過帶用戶ID的深度數據,我們可以很輕易地得到用戶在圖像中的位置與深度信息,利于后續的摳圖等等的操作。
代碼
慣例,先上代碼。
#include <Windows.h> #include <iostream> #include <NuiApi.h> #include <opencv2/opencv.hpp>using namespace std; using namespace cv;typedef struct structBGR {BYTE blue;BYTE green;BYTE red; } BGR;// 處理深度數據的每一個像素,如果屬于同一個用戶的ID,那么像素就標為同種顏色,不同的用戶, // 其ID不一樣,顏色的標示也不一樣,如果不屬于某個用戶的像素,那么就采用原來的深度值 BGR Depth2RGB(USHORT depthID) {//每像素共16bit的信息,其中最低3位是ID(所捕捉到的人的ID),剩下的13位才是信息 USHORT realDepth = (depthID & 0xfff8) >> 3; //深度信息,高13位USHORT player = depthID & 0x0007; //提取用戶ID信息,低3位//因為提取的信息是距離信息,為了便于顯示,這里歸一化為0-255BYTE depth = (BYTE)(255 * realDepth / 0x1fff);BGR color_data;color_data.blue = color_data.green = color_data.red = 0;//RGB三個通道的值都是相等的話,就是灰度的 //Kinect系統能夠處理辨識傳感器前多至6個人物的信息,但同一時刻最多只有2個玩家可被追蹤(即骨骼跟蹤)switch (player){case 0:color_data.blue = depth / 2;color_data.green = depth / 2;color_data.red = depth / 2;break;case 1:color_data.red = depth;break;case 2:color_data.green = depth;break;case 3:color_data.blue = depth;break;case 4:color_data.blue = depth;color_data.green = depth;color_data.red = depth / 4;break;case 5:color_data.blue = depth;color_data.green = depth / 4;color_data.red = depth;break;case 6:color_data.blue = depth / 4;color_data.green = depth;color_data.red = depth;break;}return color_data; }int main(int argc, char * argv[]) {cv::Mat img;img.create(240, 320, CV_8UC3);// 1、初始化NUIHRESULT hr = NuiInitialize(NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX);if (FAILED(hr)){cout << "NuiIntialize failed" << endl;return hr;}// 2、定義事件句柄 // 創建讀取下一幀的信號事件句柄,控制KINECT是否可以開始讀取下一幀數據 HANDLE nextDepthFrameEvent = CreateEvent(NULL, TRUE, FALSE, NULL);HANDLE depthStreamHandle = NULL; // 保存圖像數據流的句柄,用以提取數據 // 3、打開Kinect設備的深度圖數據通道,使用depthStreamHandle保存該數據流的句柄,以便于后續讀取hr = NuiImageStreamOpen(NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX, NUI_IMAGE_RESOLUTION_320x240, 0, 2, nextDepthFrameEvent, &depthStreamHandle);if (FAILED(hr)){cout << "Could not open color image stream video" << endl;NuiShutdown();return hr;}cv::namedWindow("depthImage", CV_WINDOW_AUTOSIZE);// 4、開始讀取深度數據while (1){const NUI_IMAGE_FRAME * pImageFrame = NULL;// 4.1、無限等待新的數據,等到后就返回if (WaitForSingleObject(nextDepthFrameEvent, INFINITE) == 0){// 4.2、從剛才打開數據流的流句柄中得到該幀的數據,讀取到的數據地址存在pImageFramehr = NuiImageStreamGetNextFrame(depthStreamHandle, 0, &pImageFrame);if (FAILED(hr)){cout << "Could not get depth image" << endl;NuiShutdown();return hr;}INuiFrameTexture * pTexture = pImageFrame->pFrameTexture;NUI_LOCKED_RECT LockedRect;// 4.3、提取數據幀到LockedRect,它包括了兩個數據對象:pitch每行字節數,pBits第一個字節地址//并鎖定數據,這樣當我們讀數據的時候,kinect就不會去修改它 pTexture->LockRect(0, &LockedRect, NULL, 0);// 4.4、確認得到的數據是否有效if (LockedRect.Pitch != 0){//4.5、將數據轉換為OpenCV的Mat格式 for (int i = 0;i < img.rows;i++){uchar * ptr = img.ptr<uchar>(i);//深度圖像數據含有兩種格式,這里像素的低12位表示一個深度值,高4位未使用;//這里是第二種:既表示深度值又含有人物序號,則像素值的高13位保存了深度值,低三位保存用戶序號,//注意這里需要轉換,因為每個數據是2個字節,存儲的同上面的顏色信息不一樣,uchar *pBufferRun = (uchar*)(LockedRect.pBits) + i * LockedRect.Pitch;USHORT * pBuffer = (USHORT*)pBufferRun;for (int j = 0;j < img.cols;j++){// ptr[j] = 255 - (uchar)(255 * pBuffer[j] / 0x0fff); //直接將數據歸一化處理// ptr[j] = (uchar)(255 * pBuffer[j] / 0x0fff); //直接將數據歸一化處理BGR rgb = Depth2RGB(pBuffer[j]);ptr[3 * j] = rgb.blue;ptr[3 * j + 1] = rgb.green;ptr[3 * j + 2] = rgb.red;}}cv::imshow("depthImage", img);}else{cout << "Buffer length of received texture is bogus\r\n" << endl;}// 5、這幀已經處理完了,將其解鎖,更新下一幀數據pTexture->UnlockRect(0);// 6、釋放這一陣數據,準備接受下一幀NuiImageStreamReleaseFrame(depthStreamHandle, pImageFrame);}if (cv::waitKey(20) == 27){break;}}// 7、關閉NUI連接NuiShutdown();return 0; } }結果
說明
代碼的套路大體上與Kinect學習(四):提取深度數據總是一樣的,只有少部分不同。一樣的地方不做贅述了,請自行查閱代碼。
1、數據讀取
- NUI初始化的參數要改為:NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX;
- 打開深度圖數據流時的圖像類型改為:NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX;
2、深度數據處理
由于這里的深度數據格式與之前不同,所以另外定義了一個函數來處理帶用戶ID的深度數據。
首先是自定義了一個結構體:
用來表示一個像素的RGB值。
然后,定義深度數據處理函數:
// 處理深度數據的每一個像素,如果屬于同一個用戶的ID,那么像素就標為同種顏色,不同的用戶, // 其ID不一樣,顏色的標示也不一樣,如果不屬于某個用戶的像素,那么就采用原來的深度值 BGR Depth2RGB(USHORT depthID) {//每像素共16bit的信息,其中最低3位是ID(所捕捉到的人的ID),剩下的13位才是信息 USHORT realDepth = (depthID & 0xfff8) >> 3; //深度信息,高13位USHORT player = depthID & 0x0007; //提取用戶ID信息,低3位//因為提取的信息是距離信息,為了便于顯示,這里歸一化為0-255BYTE depth = (BYTE)(255 * realDepth / 0x1fff);BGR color_data;color_data.blue = color_data.green = color_data.red = 0;//RGB三個通道的值都是相等的話,就是灰度的 //Kinect系統能夠處理辨識傳感器前多至6個人物的信息,但同一時刻最多只有2個玩家可被追蹤(即骨骼跟蹤)switch (player){case 0:color_data.blue = depth / 2;color_data.green = depth / 2;color_data.red = depth / 2;break;case 1:color_data.red = depth;break;case 2:color_data.green = depth;break;case 3:color_data.blue = depth;break;case 4:color_data.blue = depth;color_data.green = depth;color_data.red = depth / 4;break;case 5:color_data.blue = depth;color_data.green = depth / 4;color_data.red = depth;break;case 6:color_data.blue = depth / 4;color_data.green = depth;color_data.red = depth;break;}return color_data; }從低13位提取出深度數據,高3位提取出ID號。根據ID和深度的不同顯示不同的顏色。
參考資料
總結
以上是生活随笔為你收集整理的Kinect学习(五):提取带用户ID的深度数据的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Kinect学习(四):提取深度数据
- 下一篇: Kinect学习(六):提取人体关节点数