基於C++完成kinect+opencv 獲得深度及黑色數據。本站提示廣大學習愛好者:(基於C++完成kinect+opencv 獲得深度及黑色數據)文章只能為提供參考,不一定能成為您想要的結果。以下是基於C++完成kinect+opencv 獲得深度及黑色數據正文
開辟情況 vs2010+OPENCV2.4.10
起首,下載最新的Kinect 2 SDK http://www.microsoft.com/en-us/kinectforwindows/develop/downloads-docs.aspx
下載以後不要拔出Kinect,最好也不消拔出除鍵盤鼠標之外的其它USB裝備,然後裝置SDK,裝置完成以後拔出Kinect,會有裝置新裝備的提醒。裝置完成以後可以去“開端”那邊找到兩個新裝置的軟件,一個是可以顯示Kinect深度圖,別的一個軟件展現SDK中的各類例子法式。
進入SDK的裝置目次,可以找到sample這個文件夾,外面是四種說話編寫的例子,個中native是C++的,managed是C#的,還有別的兩種說話不熟習,我就熟習C++,橫豎只是嘗嘗的,就用C++了。
opencv+kinect .cpp
#include <opencv2\opencv.hpp> #include<iostream> //windows的頭文件,必需要,否則NuiApi.h用不了 #include <Windows.h> //Kinect for windows 的頭文件 #include "NuiApi.h" using namespace std; using namespace cv; #include <d3d11.h> //最遠間隔(mm) const int MAX_DISTANCE = 3500; //比來間隔(mm) const int MIN_DISTANCE = 200; const LONG m_depthWidth = 640; const LONG m_depthHeight = 480; const LONG m_colorWidth = 640; const LONG m_colorHeight = 480; const LONG cBytesPerPixel = 4; int main() { //黑色圖象 Mat image_rgb; //深度圖象 Mat image_depth; //創立一個MAT image_rgb.create(480,640,CV_8UC3); image_depth.create(480,640,CV_8UC1); //一個KINECT實例指針 INuiSensor* m_pNuiSensor = NULL; if (m_pNuiSensor != NULL) { return 0; } //記載以後銜接KINECT的數目(為多銜接做預備) int iSensorCount; //取得以後KINECT的數目 HRESULT hr = NuiGetSensorCount(&iSensorCount); //依照序列初始化KINETC實例,這裡就銜接了一個KINECT,所以沒有效到輪回 hr = NuiCreateSensorByIndex(iSensorCount - 1, &m_pNuiSensor); //初始化,讓其可以吸收黑色和深度數據流 hr = m_pNuiSensor->NuiInitialize(NUI_INITIALIZE_FLAG_USES_COLOR | NUI_INITIALIZE_FLAG_USES_DEPTH); //斷定能否失足 if (FAILED(hr)) { cout<<"NuiInitialize failed"<<endl; return hr; } //黑色圖象獲得下一幀事宜 HANDLE nextColorFrameEvent = CreateEvent(NULL, TRUE, FALSE, NULL); //黑色圖象事宜句柄 HANDLE colorStreamHandle = NULL; //深度圖象獲得下一幀事宜 HANDLE nextDepthFrameEvent = CreateEvent(NULL, TRUE, FALSE, NULL); //深度圖象事宜句柄 HANDLE depthStreamHandle = NULL; //實例翻開數據流,這裡NUI_IMAGE_TYPE_COLOR表現黑色圖象 hr = m_pNuiSensor->NuiImageStreamOpen(NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480, 0,2,nextColorFrameEvent,&colorStreamHandle); if( FAILED( hr ) )//斷定能否提取准確 { cout<<"Could not open color image stream video"<<endl; m_pNuiSensor->NuiShutdown(); return hr; } //實例翻開數據流,這裡NUI_IMAGE_TYPE_DEPTH表現深度圖象 hr = m_pNuiSensor->NuiImageStreamOpen(NUI_IMAGE_TYPE_DEPTH, NUI_IMAGE_RESOLUTION_640x480, 0,2, nextDepthFrameEvent, &depthStreamHandle); if( FAILED( hr ) )//斷定能否提取准確 { cout<<"Could not open color image stream video"<<endl; m_pNuiSensor->NuiShutdown(); return hr; } cv::namedWindow("depth", CV_WINDOW_AUTOSIZE); moveWindow("depth",300,600); cv::namedWindow("colorImage",CV_WINDOW_AUTOSIZE); moveWindow("colorImage",0,200); while (1) { NUI_IMAGE_FRAME pImageFrame_rgb; NUI_IMAGE_FRAME pImageFrame_depth; //無窮期待新的黑色數據,比及後前往 if (WaitForSingleObject(nextColorFrameEvent, 0) == 0) { //從適才翻開數據流的流句柄中獲得該幀數據,讀取到的數據地址存於pImageFrame hr = m_pNuiSensor->NuiImageStreamGetNextFrame(colorStreamHandle, 0, &pImageFrame_rgb); if (FAILED(hr)) { cout<<"Could not get color image"<<endl; m_pNuiSensor->NuiShutdown(); return -1; } INuiFrameTexture *pTexture = pImageFrame_rgb.pFrameTexture; NUI_LOCKED_RECT lockedRect; //提取數據幀到LockedRect,它包含兩個數據對象:pitch每行字節數,pBits第一個字節地址 //並鎖定命據,如許當我們讀數據的時刻,kinect就不會去修正它 pTexture->LockRect(0, &lockedRect, NULL, 0); //確認取得的數據能否有用 if (lockedRect.Pitch != 0) { //將數據轉換為OpenCV的Mat格局 for (int i = 0; i < image_rgb.rows; i++) { //第i行的指針 uchar *prt = image_rgb.ptr(i); //每一個字節代表一個色彩信息,直接應用uchar uchar *pBuffer = (uchar*)(lockedRect.pBits) + i * lockedRect.Pitch; for (int j = 0; j < image_rgb.cols; j++) { prt[3 * j] = pBuffer[4 * j];//外部數據是4個字節,0-1-2是BGR,第4個如今未應用 prt[3 * j + 1] = pBuffer[4 * j + 1]; prt[3 * j + 2] = pBuffer[4 * j + 2]; } } imshow("colorImage",image_rgb); //消除鎖定 pTexture->UnlockRect(0); //釋放幀 m_pNuiSensor->NuiImageStreamReleaseFrame(colorStreamHandle, &pImageFrame_rgb ); } else { cout<<"Buffer length of received texture is bogus\r\n"<<endl; } BOOL nearMode; INuiFrameTexture* pColorToDepthTexture; //深度圖象的處置 if (WaitForSingleObject(nextDepthFrameEvent, INFINITE) == 0) { hr = m_pNuiSensor->NuiImageStreamGetNextFrame(depthStreamHandle, 0 , &pImageFrame_depth); if (FAILED(hr)) { cout<<"Could not get color image"<<endl; NuiShutdown(); return -1; } hr = m_pNuiSensor->NuiImageFrameGetDepthImagePixelFrameTexture( depthStreamHandle, &pImageFrame_depth, &nearMode, &pColorToDepthTexture); INuiFrameTexture *pTexture = pImageFrame_depth.pFrameTexture; NUI_LOCKED_RECT lockedRect; NUI_LOCKED_RECT ColorToDepthLockRect; pTexture->LockRect(0, &lockedRect, NULL, 0); pColorToDepthTexture->LockRect(0,&ColorToDepthLockRect,NULL,0); //歸一化 for (int i = 0; i < image_depth.rows; i++) { uchar *prt = image_depth.ptr<uchar>(i); uchar* pBuffer = (uchar*)(lockedRect.pBits) + i * lockedRect.Pitch; //這裡須要轉換,由於每一個深度數據是2個字節,應將BYTE轉成USHORT USHORT *pBufferRun = (USHORT*)pBuffer; for (int j = 0; j < image_depth.cols; j++) { //先向,將數據歸一化處置,對深度間隔在300mm-3500mm規模內的像素,映照到【0—255】內, //超越規模的,都去做是邊沿像素 if (pBufferRun[j] << 3 > MAX_DISTANCE) prt[j] = 255; else if(pBufferRun[j] << 3 < MIN_DISTANCE) prt[j] = 0; else prt[j] = (BYTE)(256 * (pBufferRun[j] << 3)/ MAX_DISTANCE); } } imshow("depth", image_depth); //接上去是對齊部門,將遠景摳出來 //寄存深度點的參數 NUI_DEPTH_IMAGE_POINT* depthPoints = new NUI_DEPTH_IMAGE_POINT[640 * 480]; if (ColorToDepthLockRect.Pitch != 0) { HRESULT hrState = S_OK; //一個能在分歧空間坐標改變的類(包含:深度,黑色,骨骼) INuiCoordinateMapper* pMapper; //設置KINECT實例的空間坐標系 hrState = m_pNuiSensor->NuiGetCoordinateMapper(&pMapper); if (FAILED(hrState)) { return hrState; } //主要的一步:從色彩空間映照到深度空間。參數解釋: //【參數1】:黑色圖象的類型 //【參數2】:黑色圖象的分辯率 //【參數3】:深度圖象的分辯率 //【參數4】:深度圖象的個數 //【參數5】:深度像素點數 //【參數6】:取內存的年夜小,個數。類型為NUI_DEPTH_IMAGE_PIXEL //【參數7】:寄存映照成果點的參數 hrState = pMapper->MapColorFrameToDepthFrame(NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480, NUI_IMAGE_RESOLUTION_640x480, 640 * 480, (NUI_DEPTH_IMAGE_PIXEL*)ColorToDepthLockRect.pBits,640 * 480, depthPoints); if (FAILED(hrState)) { return hrState; } //顯示的圖象 Mat show; show.create(480,640,CV_8UC3); show = 0; for (int i = 0; i < image_rgb.rows; i++) { for (int j = 0; j < image_rgb.cols; j++) { uchar *prt_rgb = image_rgb.ptr(i); uchar *prt_show = show.ptr(i); //在內存中偏移量 long index = i * 640 + j; //從保留了映照坐標的數組中獲得點 NUI_DEPTH_IMAGE_POINT depthPointAtIndex = depthPoints[index]; //界限斷定 if (depthPointAtIndex.x >= 0 && depthPointAtIndex.x < image_depth.cols && depthPointAtIndex.y >=0 && depthPointAtIndex.y < image_depth.rows) { //深度斷定,在MIN_DISTANCE與MAX_DISTANCE之間確當成遠景,顯示出來 //這個應用也很主要,當應用真實的深度像素點再在深度圖象中獲得深度值來斷定的時刻,會失足 if (depthPointAtIndex.depth >= MIN_DISTANCE && depthPointAtIndex.depth <= MAX_DISTANCE) { prt_show[3 * j] = prt_rgb[j * 3]; prt_show[3 * j + 1] = prt_rgb[j * 3 + 1]; prt_show[3 * j + 2] = prt_rgb[j * 3 + 2]; } } } } imshow("show", show); } delete []depthPoints; pTexture->UnlockRect(0); m_pNuiSensor->NuiImageStreamReleaseFrame(depthStreamHandle, &pImageFrame_depth); } else { cout<<"Buffer length of received texture is bogus\r\n"<<endl; } } if (cvWaitKey(20) == 27) break; } return 0; }