Tuesday, December 26, 2017

realsense - get started with realsense stream 開始使用RealSense SR300感應器

這裡是使用 Intel® RealSense™ Camera SR300 作實驗的初心者實驗

包含了讀取Realsens感應器的串流(彩色影像、深度影像、IR圖)

以及將擷取到的影像使用OpenCV的library顯示及儲存

--

#include <iostream>
#include <direct.h>
#include <string>
#include <time.h>
#include "opencv2\opencv.hpp"
#include "librealsense\pxcsensemanager.h"

cv::Mat PXCImage2CVMat(PXCImage *pxcImage, PXCImage::PixelFormat format)
{
 PXCImage::ImageData data;
 pxcImage->AcquireAccess(PXCImage::ACCESS_READ, format, &data);

 int width = pxcImage->QueryInfo().width;
 int height = pxcImage->QueryInfo().height;

 if (!format)
  format = pxcImage->QueryInfo().format;

 int type = 0;
 if (format == PXCImage::PIXEL_FORMAT_Y8)  //讀IR
  type = CV_8UC1;
 else if (format == PXCImage::PIXEL_FORMAT_RGB24) //讀彩色
  type = CV_8UC3;
 else if (format == PXCImage::PIXEL_FORMAT_DEPTH_F32) //比較容易看懂的深度圖(黑白黑白區隔)
  type = CV_32FC1;
 else if (format == PXCImage::PIXEL_FORMAT_DEPTH) //一般的深度圖
  type = CV_16UC1;
 else if (format == PXCImage::PIXEL_FORMAT_DEPTH_RAW) //千層麵深度圖
  type = CV_16UC1;

 cv::Mat ocvImage = cv::Mat(cv::Size(width, height), type, data.planes[0]);

 pxcImage->ReleaseAccess(&data);
 return ocvImage;
}

int main()
{
 PXCSession *session = PXCSession::CreateInstance();
 PXCSenseManager *sm = PXCSenseManager::CreateInstance();

 cv::Size frameSize = cv::Size(640, 480);
 float frameRate = 60;
 cv::Mat frameColor = cv::Mat::zeros(frameSize, CV_8UC3);
 cv::Mat frameDepth = cv::Mat::zeros(frameSize, CV_8UC1);
 cv::Mat frameIR = cv::Mat::zeros(frameSize, CV_8UC1);
 
 //啟動串流
 sm->EnableStream(PXCCapture::STREAM_TYPE_COLOR, frameSize.width, frameSize.height, frameRate);
 sm->EnableStream(PXCCapture::STREAM_TYPE_DEPTH, frameSize.width, frameSize.height, frameRate);
 sm->EnableStream(PXCCapture::STREAM_TYPE_IR, frameSize.width, frameSize.height, frameRate);
 sm->Init();

 //設定資料夾名稱
 std::string folderName = ".\\data";
 std::string colorFileName = folderName + "\\color";
 std::string depthFileName = folderName + "\\depth";
 std::string irFileName = folderName + "\\IR";

 //新增資料夾
 _mkdir(folderName.c_str());
 _mkdir((colorFileName).c_str());
 _mkdir((depthFileName).c_str());
 _mkdir((irFileName).c_str());

 clock_t startTime;
 startTime = clock();

 bool storeImg = false;

 for (;;)
 {
  if (sm->AcquireFrame(true) < PXC_STATUS_NO_ERROR)
  {
   std::cout << "No input Frame" << std::endl;
   break;
  }

  PXCCapture::Sample *sample;
  sample = sm->QuerySample();


  if (sample->color)
  {
   frameColor = PXCImage2CVMat(sample->color, PXCImage::PIXEL_FORMAT_RGB24);
  }

  if (sample->depth)
  {
   //frameDepth = PXCImage2CVMat(sample->depth, PXCImage::PIXEL_FORMAT_DEPTH_F32);
   //frameDepth = PXCImage2CVMat(sample->depth, PXCImage::PIXEL_FORMAT_DEPTH_RAW);
   frameDepth = PXCImage2CVMat(sample->depth, PXCImage::PIXEL_FORMAT_DEPTH);
  }

  if (sample->ir)
  {
   frameIR = PXCImage2CVMat(sample->ir, PXCImage::PIXEL_FORMAT_Y8);
  }

  cv::imshow("color", frameColor);
  cv::imshow("Depth", frameDepth);
  cv::imshow("ir", frameIR);

  
  if (cv::waitKey(27) == 13) //按下Enter開始不斷儲存照片直到下次按下Enter為止
  {
   storeImg = !storeImg;
   if (storeImg)
   {
    std::cout << "START CAPTURE" << std::endl;
   }
   else
   {
    std::cout << "FINISHED CAPTURE" << std::endl;
   }
  }

  if (storeImg) //儲存圖片
  {
   clock_t nowsTime = clock() - startTime;
   std::cout << "Time : " << ((float)nowsTime) / CLOCKS_PER_SEC << "(sec)" << std::endl;
   float nowsTime_str = ((float)nowsTime) / CLOCKS_PER_SEC;

   cv::imwrite(colorFileName + "\\" + std::to_string(nowsTime_str) + ".png", frameColor);
   cv::imwrite(depthFileName + "\\" + std::to_string(nowsTime_str) + ".png", frameDepth);
   cv::imwrite(irFileName + "\\" + std::to_string(nowsTime_str) + ".png", frameIR);
  }
  
  sm->ReleaseFrame();
 }

 system("pause");
 return 0;
}

--
實驗結果

這張圖是run下去後會應該會跑出的畫面

從左至右分別是 彩色影像、IR圖、深度圖

深度圖因為本身就很難用肉眼辨識的關係會覺得一團黑

實際上圖是有些微變化的 ( 讀取圖像數值的話就知道了!)


--

如果旨在看得見或是有其他用途的話

可以把我中間程式碼註解掉的這段程式碼拿來用看看 (三選一的意思)



  frameDepth = PXCImage2CVMat(sample->depth, PXCImage::PIXEL_FORMAT_DEPTH_F32);
  frameDepth = PXCImage2CVMat(sample->depth, PXCImage::PIXEL_FORMAT_DEPTH_RAW);
  frameDepth = PXCImage2CVMat(sample->depth, PXCImage::PIXEL_FORMAT_DEPTH);

其中
 PIXEL_FORMAT_DEPTH_F32
 PIXEL_FORMAT_DEPTH_RAW
 PIXEL_FORMAT_DEPTH

是讀取深度圖的不同方法

我平時在做3D投射是需要使用最下面這個 PIXEL_FORMAT_DEPTH



下圖是三種方式的比較

右下角為IR圖 (因為IR圖和深度圖是可以相對應的, 所以放在一起比較)




No comments:

Post a Comment