一、簡要介紹
關于realsense的介紹,網上很多,這裡不再贅述,sdk及相關文檔可參考realsense SDK,也可參考開發人員專區。
運作代碼之前,要確定你已經安裝好了realsense的DCM和SDK,官網有教程,具體請參考DCM和SDK安裝步驟。
二、代碼
#include <pxcsensemanager.h>
#include <pxcsession.h>
#include "util_render.h"
#include <iostream>
#include <string>
#include <stdio.h>
#include <opencv2\opencv.hpp>
#include <windows.h>
#define WIDTH 640
#define HEIGHT 480
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
UtilRender *renderColor = new UtilRender(L"COLOR_STREAM");
UtilRender *renderDepth = new UtilRender(L"DEPTH_STREAM");
PXCSenseManager *psm = 0;
psm = PXCSenseManager::CreateInstance();
if (!psm)
{
wprintf_s(L"Unabel to create the PXCSenseManager\n");
return 1;
}
pxcStatus sts;
psm->EnableStream(PXCCapture::STREAM_TYPE_COLOR, WIDTH, HEIGHT);
psm->EnableStream(PXCCapture::STREAM_TYPE_DEPTH, WIDTH, HEIGHT);
sts = psm->Init();
if (sts != PXC_STATUS_NO_ERROR)
{
wprintf_s(L"Unabel to Initializes the pipeline\n");
return 2;
}
PXCImage *colorIm, *depthIm;
PXCImage::ImageData depth_data,color_data;
PXCImage::ImageInfo depth_info,color_info;
while (psm->AcquireFrame(true) >= PXC_STATUS_NO_ERROR)
{
if (psm->AcquireFrame(true) < PXC_STATUS_NO_ERROR) break;
PXCCapture::Sample *sample = psm->QuerySample();
colorIm = sample->color;
depthIm = sample->depth;
if (colorIm->AcquireAccess(PXCImage::ACCESS_READ, PXCImage::PIXEL_FORMAT_RGB24, &color_data) < PXC_STATUS_NO_ERROR)
wprintf_s(L"未正常擷取彩色圖\n");
if (depthIm->AcquireAccess(PXCImage::ACCESS_READ, &depth_data) < PXC_STATUS_NO_ERROR)
wprintf_s(L"未正常擷取深度圖\n");
depth_info = sample->depth->QueryInfo();
color_info = sample->color->QueryInfo();
Mat depth(Size(depth_info.width, depth_info.height), CV_16UC1, (void*)depth_data.planes[0], depth_data.pitches[0] / sizeof(uchar));
Mat color(Size(color_info.width, color_info.height), CV_8UC3, (void*)color_data.planes[0], color_data.pitches[0] / sizeof(uchar));
depthIm->ReleaseAccess(&depth_data);
colorIm->ReleaseAccess(&color_data);
if (!renderColor->RenderFrame(colorIm)) break;
if (!renderDepth->RenderFrame(depthIm)) break;
psm->ReleaseFrame();
imshow("color", color);
waitKey(1);
//CV_16UC1的圖檔在imshow時會除以256,将最遠探測距離設為z,那麼imshow時可以乘以255*256/z,此處乘以15
imshow("depth", depth * 15);
waitKey(1);
}
psm->Release();
system("pause");
}
三、相關解釋
建立項目,寫入源代碼,生成解決方案之前,記得要在項目的屬性管理器右鍵項目,選擇添加現有屬性表,選擇C:\Program Files (x86)\Intel\RSSDK\props目錄下的一個官方配置好的屬性表(前提是DCM和SDK的安裝路徑是預設路徑,沒有自行修改);另外因為我們還要進行cv::Mat類型的轉化,是以也要導入opencv的屬性表。
運作之後,可以看到4個視窗,COLOR_STREAM和DEPTH_STREAM為分别realsense提取到的彩色視訊流和深度視訊流;color和depth分别為我們轉化為opencv中mat類型之後的彩色和深度視訊流。

目前實作pxcimage到mat類型轉化的方法有好幾種,大體類似,主要是對PXCImage::ImageData中的plane和pitch的了解,部落客了解為plane[0]為該sdk中圖檔資料的首位址,pitches可參考http://www.cnblogs.com/gamedes/p/4541765.html。
也看到論壇上有人專門寫過pxcimage到mat類型的轉化函數,函數代碼如下:
void ConvertPXCImageToOpenCVMat(PXCImage *inImg, Mat *outImg) {
int cvDataType;
int cvDataWidth;
PXCImage::ImageData data;
inImg->AcquireAccess(PXCImage::ACCESS_READ, &data);
PXCImage::ImageInfo imgInfo = inImg->QueryInfo();
switch (data.format) {
/* STREAM_TYPE_COLOR */
case PXCImage::PIXEL_FORMAT_YUY2: /* YUY2 image */
case PXCImage::PIXEL_FORMAT_NV12: /* NV12 image */
throw(0); // Not implemented
case PXCImage::PIXEL_FORMAT_RGB32: /* BGRA layout on a little-endian machine */
cvDataType = CV_8UC4;
cvDataWidth = 4;
break;
case PXCImage::PIXEL_FORMAT_RGB24: /* BGR layout on a little-endian machine */
cvDataType = CV_8UC3;
cvDataWidth = 3;
break;
case PXCImage::PIXEL_FORMAT_Y8: /* 8-Bit Gray Image, or IR 8-bit */
cvDataType = CV_8U;
cvDataWidth = 1;
break;
/* STREAM_TYPE_DEPTH */
case PXCImage::PIXEL_FORMAT_DEPTH: /* 16-bit unsigned integer with precision mm. */
case PXCImage::PIXEL_FORMAT_DEPTH_RAW: /* 16-bit unsigned integer with device specific precision (call device->QueryDepthUnit()) */
cvDataType = CV_16U;
cvDataWidth = 2;
break;
case PXCImage::PIXEL_FORMAT_DEPTH_F32: /* 32-bit float-point with precision mm. */
cvDataType = CV_32F;
cvDataWidth = 4;
break;
/* STREAM_TYPE_IR */
case PXCImage::PIXEL_FORMAT_Y16: /* 16-Bit Gray Image */
cvDataType = CV_16U;
cvDataWidth = 2;
break;
case PXCImage::PIXEL_FORMAT_Y8_IR_RELATIVE: /* Relative IR Image */
cvDataType = CV_8U;
cvDataWidth = 1;
break;
}
// suppose that no other planes
if (data.planes[1] != NULL) throw(0); // not implemented
// suppose that no sub pixel padding needed
if (data.pitches[0] % cvDataWidth!=0) throw(0); // not implemented
outImg->create(imgInfo.height, data.pitches[0] / cvDataWidth, cvDataType);
memcpy(outImg->data, data.planes[0], imgInfo.height*imgInfo.width*cvDataWidth*sizeof(pxcBYTE));
inImg->ReleaseAccess(&data);
}
原則上傳入pxcimage的指針,再通過case根據原圖像類型選擇要轉化的圖像類型是沒有問題的,部落客嘗試過使用這個函數,但總會出現R1060的錯誤,似乎是指針非法使用。大家可以自行嘗試一下,成功的小夥伴麻煩告知一下部落客,讓部落客學習學習。