Help us understand the problem. What is going on with this article?

RealSenseをcv2.VideoCaptureライクに使う

RealSenseとは

Intelが作っているDepthカメラシリーズです。
今回D415を使います。
このRealSenseをOpenCVで使うとき、通常のWebカメラと同じように cv2.VideoCapture(0) とできなくて面倒だったので、VideoCaptureと同じように使えるクラスを作成しました。

依存関係

  • pyrealsense2
  • numpy

どちらもpipでインストールできます。

2019/10/11 追記

MacやJetson Nanoなど,ArmチップのCPUではpipでpyrealsense2がインストールできないようです.sourceからbuildする必要があります.

コード

下記のクラスが cv2.VideoCapture の代わりになるものです。

realsensecv.py
import pyrealsense2 as rs
import numpy as np


class RealsenseCapture:

    def __init__(self):
        self.WIDTH = 640
        self.HEGIHT = 480
        self.FPS = 30
        # Configure depth and color streams
        self.config = rs.config()
        self.config.enable_stream(rs.stream.color, self.WIDTH, self.HEGIHT, rs.format.bgr8, self.FPS)
        self.config.enable_stream(rs.stream.depth, self.WIDTH, self.HEGIHT, rs.format.z16, self.FPS)

    def start(self):
        # Start streaming
        self.pipeline = rs.pipeline()
        self.pipeline.start(self.config)
        print('pipline start')

    def read(self, is_array=True):
        # Flag capture available
        ret = True
        # get frames
        frames = self.pipeline.wait_for_frames()
        # separate RGB and Depth image
        self.color_frame = frames.get_color_frame()  # RGB
        self.depth_frame = frames.get_depth_frame()  # Depth

        if not self.color_frame or not self.depth_frame:
            ret = False
            return ret, (None, None)
        elif is_array:
            # Convert images to numpy arrays
            color_image = np.array(self.color_frame.get_data())
            depth_image = np.array(self.depth_frame.get_data())
            return ret, (color_image, depth_image)
        else:
            return ret, (self.color_frame, self.depth_frame)

    def release(self):
        # Stop streaming
        self.pipeline.stop()

今回 realsensecv.py という名前で保存して、他のファイルからimportします。

Example

上記のクラスを用いてリアルタイムに映像を出力してみます。

rs_streaming.py
# coding: utf-8
import cv2
import numpy as np
from realsensecv import RealsenseCapture


cap = RealsenseCapture()
# プロパティの設定
cap.WIDTH = 640
cap.HEIGHT = 480
cap.FPS = 30
# cv2.VideoCapture()と違ってcap.start()を忘れずに
cap.start()

while True:
    ret, frames = cap.read()  # frames[0]にRGB、frames[1]にDepthの画像がndarrayが入っている
    color_frame = frames[0]
    depth_frame = frames[1]
    # ヒートマップに変換
    depth_colormap = cv2.applyColorMap(cv2.convertScaleAbs(
        depth_frame, alpha=0.08), cv2.COLORMAP_JET)
    # レンダリング
    images = np.hstack((color_frame, depth_colormap))  # RGBとDepthを横に並べて表示
    cv2.imshow('RealSense', images)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# ストリーミング停止
cap.release()
cv2.destroyAllWindows()

pyrealsense2ではdepth_frameから距離を取得する get_distance メソッドなどがありますが、RealsenseCaptureで出力されるdepth_frameにはそのメソッドはありません。
get_distance などを使いたい場合は、インスタンス変数にアクセスしてください。

下記にクリックしたピクセルの距離を取得する例を載せます。

get_distance.py
# coding: utf-8

import cv2
import numpy as np
from realsensecv import RealsenseCapture


# マウスイベント時に処理を行う
def mouse_event(event, x, y, flags, param):
    depth_frame = param
    distance = depth_frame.get_distance(x, y)
    # 左クリックで座標を返す
    if event == cv2.EVENT_LBUTTONUP:
        return print(distance)

cap = RealsenseCapture()
cap.start()

while True:
    ret, frames = cap.read()
    color_frame = frames[0]
    depth_frame = frames[1]
    # ヒートマップに変換
    depth_colormap = cv2.applyColorMap(cv2.convertScaleAbs(
        depth_frame, alpha=0.08), cv2.COLORMAP_JET)
    # レンダリング
    images = np.hstack((color_frame, depth_colormap))
    cv2.namedWindow('RealSense', cv2.WINDOW_AUTOSIZE)
    cv2.imshow('RealSense', images)

    # マウスイベント時に関数mouse_eventの処理を行う
    cv2.setMouseCallback('RealSense', mouse_event, cap.depth_frame)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# ストリーミング停止
cap.release()
cv2.destroyAllWindows()

これでVideoCaptureのように使えて、既存のコードを簡単に使いまわせるようになりました!
ミスや改善点などあればコメントお願いしますm(_ _)m

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away