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
の代わりになるものです。
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
上記のクラスを用いてリアルタイムに映像を出力してみます。
# 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
などを使いたい場合は、インスタンス変数にアクセスしてください。
下記にクリックしたピクセルの距離を取得する例を載せます。
# 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