|

【3D感測器】如何擷取Intel RealSense™串流影像到OpenCV

   
作者:許哲豪 Jack

上次已透過「【3D感測器】Intel RealSense™ SDK無痛安裝指引」一文幫大家說明如何安裝,這次就幫大家說明如何從RealSense SDK擷取彩色、深度及紅外線串流影像並導入OpenCV中,方便後續開發自己的人機介面及相關計算功能。

Intel RealSense串流影像導入OpenCV Mat示意圖 (OmniXRI整理繪製)

我想大部份的人想開發一個3D的人機介面可以自由平移、縮放及旋轉視角是有點(大誤!是非常)困難的,所以RealSense SDK提供使用者輕易切換2D(平面)及3D(立體、深度)顯示及操作的介面。這項功能是基於通用3D繪圖引擎OpenGL達成的,雖然很方便操作,但於習慣自己用Visual Studio、QT及其它GUI工具開發人機介面程式的人反而有點不太方便,尤其是重度OpenCV使用者無法透過常用的VideoCapture函式直接取得RealSense各攝影機的串流影像,更是造成一些小困擾。

目前官方SDK範例程式"C:\Program Files (x86)\Intel RealSense SDK 2.0\samples\im-show\rs-imshow.cpp"可以讀取彩像影像和著虛擬色後的深度影像並傳至OpenCV Mat中再透過imshow函式進行顯示,但無法讀取紅外線影像。經過一番查找後,終於找到如何設定,首先建構一組接收管道(pipeline),再設定欲接收的串流影像類型及細部配置參數(config),接著就可以啟動(start)串流影像接收管道,最後把接收到的影格(frame)轉換成OpenCV Mat格式,就可透過imshow顯示或作其它處理使用。

這裡要注意的是,由於RealSense D435可以提供不同格式的影像(8bit, 16bit),而OpenCV只能顯示8bit,所以如遇到要顯示或運算16bit影像時要記得利用像convertScaleAbs之類的函式將16bit轉回8bit,才能正常處理。另外如果想轉存這些串流影像,則使用OpenCV VideoCapture及 VideoWriter函式處理即可。完整的範例如下所示,相關說明已於程式上註解,就不多贅述。

#include  // 引入RealSense標頭檔

#include // 引入OpenCV標頭檔

using namespace std; // 使用std標準函式命名空間

using namespace cv; // 使用OpenCV函式命名空間

// 主程式入口

int main(int argc, char * argv) try

{

// 建構一個RealSense抽象設備的管道以容納擷取到的影像

rs2::pipeline pipe;

// 創建自定義參數以配置管道

rs2::config cfg;

// 設定影像尺寸(寬w,高h)

const int w = 640;

const int h = 480;

// 設定欲顯示的影像流(可依需求啟動不一定要全設)

cfg.enable_stream(RS2_STREAM_COLOR, w, h, RS2_FORMAT_BGR8, 30); // BGR888格式彩色影像 30fps

cfg.enable_stream(RS2_STREAM_DEPTH, w, h, RS2_FORMAT_Z16, 30); // 16 bit格式灰階深度影像 30fps

cfg.enable_stream(RS2_STREAM_INFRARED, 1, w, h, RS2_FORMAT_Y8, 30); // 8 bit格式左紅外線影像 30fps

cfg.enable_stream(RS2_STREAM_INFRARED, 2, w, h, RS2_FORMAT_Y8, 30); // 8 bit格式右紅外線影像 30fps

// 根據設定值啟動指定串流影像

pipe.start(cfg);

// 宣告深度(灰階)影像著虛擬色彩對應表

rs2::colorizer color_map;

while (waitKey(1) < 0) // 若有按鍵則結束顯示串流影像

{

// 等待下一組影像

rs2::frameset frames = pipe.wait_for_frames();

// 取得每一張影像(可依需求不一定要全取)

rs2::frame color_frame = frames.get_color_frame(); // 彩色影像

rs2::frame depth_frame = frames.get_depth_frame().apply_filter(color_map); // 著虛擬色彩之深度影像

rs2::frame irL_frame = frames.get_infrared_frame(1); // 左紅外線灰階影像

rs2::frame irR_frame = frames.get_infrared_frame(2); // 右紅外線灰階影像

// 建立OpenCV Mat格式之影像(可依需求不一定要全建立)

Mat color_image(Size(w, h), CV_8UC3, (void*)color_frame.get_data(), Mat::AUTO_STEP); // 彩色影像

Mat depth_image(Size(w, h), CV_8UC3, (void*)depth_frame.get_data(), Mat::AUTO_STEP); // 著虛擬色彩之深度影像

Mat irL_image(Size(w, h), CV_8UC1, (void*)irL_frame.get_data(), Mat::AUTO_STEP); // 左紅外線灰階影像

Mat irR_image(Size(w, h), CV_8UC1, (void*)irR_frame.get_data(), Mat::AUTO_STEP); // 右紅外線灰階影像

// 以OpenCV函式顯示擷取到影像(可依需求不一定要全顯示)

imshow("Color Image", color_image); // 彩色影像

imshow("Depth Image", depth_image); // 著虛擬色彩之深度影像

imshow("Left IR Image", irL_image); // 左紅外線灰階影像

imshow("Right IR Image", irR_image); // 右紅外線灰階影像

}

return EXIT_SUCCESS;

}

catch (const rs2::error & e) // 擷取錯誤呼叫碼及顯示

{

std::cerr << "RealSense error calling " << e.get_failed_function() << "(" << e.get_failed_args() << "):\n " << e.what() << std::endl;

return EXIT_FAILURE;

}

catch (const std::exception& e) // 擷取意外錯誤及顯示

{

std::cerr << e.what() << std::endl;

return EXIT_FAILURE;

}

小結

Intel RealSense SDK提供了很方便的2D/3D操作介面,但如果想透過OpenCV存取其產生的彩色、深度及紅外線串流影像進而產生客製化介面或更複雜應用,相信本文一定可以幫到大家。

參考文獻

【3D感測器】Intel RealSense™ SDK無痛安裝指引

(本文轉載自歐尼克斯實境互動工作室原文連結;責任編輯:林亮潔)
本文為會員限定文章

立即加入會員! 全站文章無限看~

                               

已經是會員? 按此登入

只需不到短短一分鐘...

輸入您的信箱與ID註冊即可享有一切福利!

會員福利
1

免費電子報

2

會員搶先看

3

主題訂閱

4

好文收藏

許 哲豪

Author: 許 哲豪

工作經驗超過二十年,主要專長機電整合、電腦視覺、人機互動、人工智慧、專利分析及新創輔導。曾任機電整合工程師、機器視覺研發副理、技轉中心商業發展經理。目前擔任多家公司兼任技術顧問並積極推廣實境互動相關技術。 主持歐尼克斯實境互動工作室(OmniXRI):http://omnixri.blogspot.com Edge AI Taiwan邊緣智能交流區:https://www.facebook.com/groups/edgeaitw/

Share This Post On

2 Comments

  1. 您好,請問可以請您說明如何在Ubuntu系統下,用visual studio code 配置可以使用librealsense嗎

    Post a Reply

Submit a Comment

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *