上次已透過「【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註冊即可享有一切福利!
會員福利
免費電子報
會員搶先看
主題訂閱
好文收藏
2020/10/24
您好,請問可以請您說明如何在Ubuntu系統下,用visual studio code 配置可以使用librealsense嗎
2020/10/26
您可以參考一下官方提供的文件
https://github.com/IntelRealSense/librealsense/blob/master/doc/installation.md