cv::VideoCaptureでRealSenseからデータを取得する


この投稿はOpenCV Advent Calendar 2018の9日目の記事です。

はじめに

この記事では、OpenCV 4.0からサポートされたcv::VideoCaptureでRealSenseからデータを取得する方法について紹介します。

動作確認環境

  • RealSense D415/D435 (FW 5.10.13)
  • Windows 10 Pro (1809)
  • Visual Studio 2017 (15.9.3)
  • OpenCV 4.0.0
  • RealSense SDK 2.17.0
  • CMake 3.13.1

RealSenseとは?

RealSenseとは、Intelから発売されているRGB-Dセンサーです。
RealSenseには過去にもいくつかのモデルが存在しますが、現行のモデルはRealSense D400シリーズ(RealSense D415、RealSense D435、RealSense D435iなど)になります。

RealSense D400シリーズはInfraredのステレオカメラを搭載してDepthを計算します。(厳密には、赤外線波長をカットしていないRGBまたはGrayscaleのカメラです。)
ステレオカメラなのでテクスチャの乏しいシーンは苦手ですが、RealSense D400シリーズではプロジェクターからInfraredのパターンを投影してテクスチャを補うことができます。よく勘違いされますが、Kinect v1のようなStructured Light方式ではありません。

RealSense D400シリーズは、RealSense SDK 2.xを使用してデータを取得することができます。
このSDKを直接利用してデータを取得してもよいですが、この記事ではOpenCVのcv::VideoCaptureで他のカメラと同じようにデータを取得する方法を紹介します。1

RealSense D415

RealSense D435

OpenCVでRealSenseからデータを取得する方法

RealSenseをサポートしたOpenCVをビルド、インストールする

公式に配布されいてるビルド済みのOpenCVはRealSenseのサポートが有効になっていません。まずは、OpenCVをソースコードからビルドしましょう。OpenCVのビルド方法の詳細については、多くの記事があるのでそちらを参考にしてください。

ここでは、要点だけをまとめておきます。

  1. RealSense SDKをダウンロード、インストールする。

  2. OpenCVのソースコードをダウンロード、バグを修正する。

  3. CMakeで以下の設定を行う。

    • LIBREALSENSE
      • LIBREALSENSE_INCLUDE_DIR C:/Program Files (x86)/Intel RealSense SDK 2.0/include
      • LIBREALSENSE_LIBRARIES C:/Program Files (x86)/Intel RealSense SDK 2.0/lib/x86/realsense2.lib(またはC:/Program Files (x86)/Intel RealSense SDK 2.0/lib/x64/realsense2.lib)
    • WITH
      • WITH_LIBREALSENSE ☑(check)
  4. 生成したOpenCVのプロジェクトをビルド、インストールする。

cv::VideoCaptureでRealSenseからデータを取得する

main.cpp
#include <opencv2/opencv.hpp>

int main( int argc, char* argv[] )
{
    // (1) Open cv::VideoCapture() with RealSense
    cv::VideoCapture capture( cv::VideoCaptureAPIs::CAP_INTELPERC );
    if( !capture.isOpened() ){
        return -1;
    }

    while( true ){
        // (2) Grab All Frames
        capture.grab();

        // (3) Retrieve Each Frames
        // (3.1) Color Frame
        cv::Mat color_frame;
        capture.retrieve( color_frame, cv::CAP_INTELPERC_IMAGE );

        // (3.2) Depth Frame
        cv::Mat depth_frame;
        capture.retrieve( depth_frame, cv::CAP_INTELPERC_DEPTH_MAP );

        // (3.3) Infrared Frame
        cv::Mat infrared_frame;
        capture.retrieve( infrared_frame, cv::CAP_INTELPERC_IR_MAP );

        // (4) Show Image
        cv::imshow( "Color", color_frame );
        depth_frame.convertTo( depth_frame, CV_8U, -255.0 / 10000.0, 255.0 ); // Scaling
        cv::imshow( "Depth", depth_frame );
        cv::imshow( "Infrared", infrared_frame );

        const int32_t key = cv::waitKey( 33 );
        if( key == 'q' ){
            break;
        }
    }

    cv::destroyAllWindows();

    return 0;
}

(1) Open cv::VideoCapture() with RealSense

// (1) Open cv::VideoCapture() with RealSense
cv::VideoCapture capture( cv::VideoCaptureAPIs::CAP_INTELPERC );
if( !capture.isOpened() ){
    return -1;
}

cv::VideoCapture()cv::VideoCaptureAPIs::CAP_INTELPERCを指定することでRealSenseからキャプチャできます。
CAP_INTELPERCなのは、祖先にあたるIntel Perceptual Computing SDKの名残りですね。

(2) Grab All Frames

// (2) Grab All Frames
capture.grab();

cv::VideoCapture::grab()を呼ぶことで、フレームの取得を待ちます。

(3) Retrieve Each Frames

// (3) Retrieve Each Frames
// (3.1) Color Frame
cv::Mat color_frame;
capture.retrieve( color_frame, cv::CAP_INTELPERC_IMAGE );

// (3.2) Depth Frame
cv::Mat depth_frame;
capture.retrieve( depth_frame, cv::CAP_INTELPERC_DEPTH_MAP );

// (3.3) Infrared Frame
cv::Mat infrared_frame;
capture.retrieve( infrared_frame, cv::CAP_INTELPERC_IR_MAP );

cv::VideoCapture::retrieve()cv::Matにフレームを取得します。
第2引数にcv::CAP_INTELPERC_IMAGEを指定することでColor、cv::CAP_INTELPERC_DEPTH_MAPを指定することでDepth、cv::CAP_INTELPERC_IR_MAPを指定することでInfraredのフレームをそれぞれ取得することができます。
ColorはCV_8UC3(BGR)、DepthはCV_16UC1、InfraredはCV_8UC1のフォーマットでデータが格納されています。

(4) Show Image

// (4) Show Image
cv::imshow( "Color", color_frame );
depth_frame.convertTo( depth_frame, CV_8U, -255.0 / 10000.0, 255.0 ); // Scaling
cv::imshow( "Depth", depth_frame );
cv::imshow( "Infrared", infrared_frame );

DepthはCV_16UC1のフォーマットのため、そのまま可視化できません。
ここでは、CV_16U([0, 10000])をCV_8U([255, 0])にスケーリングして表示しています。

実行結果

OpenCVのRealSenseサポートについて検討する

OpenCVでは他のカメラと同じようにRealSenseを簡単に扱うことができます。
安価で手軽に利用できるRGB-Dセンサーを簡単に扱えることは大きな利点ですね。
ただし、未実装の機能や制限も多く、まだ実用に耐えられるものではないかもしれません。
これらの機能を使いたいときは、RealSense SDKを直接利用するべきでしょう。1

未実装機能

  • 解像度、フレームレート、フォーマットの設定、取得
  • ステレオカメラの両方のフレームを取得
  • ファイルからのキャプチャ
  • 複数台のRealSenseのサポート

おわりに

この記事では、OpenCVのcv::VideoCaptureでRealSenseからデータを取得する方法について紹介しました。
明日もすーぱーUnaさんたいむで「cv::kinfu::KinFuでKinect FusionをRealSenseで動かしてみる」です。


  1. もちろん、RealSense SDKを直接利用してデータを取得する方が柔軟に対応できます。RealSense SDKのサンプルを公開しているので、興味がある方はこちらを参考にしてください。