この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
1 はじめに
CX事業本部の平内(SIN)です。
前回、「カメラの前に商品をかざしたタイミングで、商品を推論したい」という事で、超音波距離センサーで試してみました。
今回は、別のアプローチとして、depthカメラを試してみました。
使用させて頂いたのは、インテル Realsence LiDARカメラ D435iは、深度計測が可能なステレオビジョンの深度カメラです。
2 動作確認
以下の動画は、動作確認している様子です。
画像の右側は、RBGのオリジナル画像です。そして、左側は、深度カメラで一定の距離以下を検出し、それ以外の部分を白色で塗り潰した画像です。また、背景色が一定値以下になると、コンソールに「検出」と表示しています。
3 Python Wrapper
RaealSenceは、公式のラッパーをインストールし、Pythonから利用しています。
IntelRealSense/librealsense/wrappers/python/
% git clone https://github.com/IntelRealSense/librealsense.git
% cd librealsense
% mkdir build && cd build
% which python3
/usr/bin/python3
% cmake .. -DBUILD_EXAMPLES=true -DBUILD_WITH_OPENMP=false -DHWM_OVER_XU=false -DBUILD_PYTHON_BINDINGS=true -DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/python3 -G "Unix Makefiles"
% make
% sudo make install
作成されたモジュールは、以下のようになっています。
% ls /usr/local/lib/pyrealsense*
/usr/local/lib/pyrealsense2.2.34.0.cpython-37m-darwin.so /usr/local/lib/pyrealsense2.cpython-37m-darwin.so
/usr/local/lib/pyrealsense2.2.34.cpython-37m-darwin.so
Pythonから利用可能なように、site-packagesにリンクを置きました。
% cd /Users/hirauchi.shinichi/.local/lib/python3.7/site-packages
% sudo ln -s /usr/local/lib/pyrealsense2.cpython-37m-darwin.so pyrealsense2.so
% sudo ln -s /usr/local/lib/pybackend2.cpython-37m-darwin.so pybackend2.so
% ls -la
lrwxr-xr-x 1 root staff 47 10 6 13:02 pybackend2.so -> /usr/local/lib/pybackend2.cpython-37m-darwin.so
lrwxr-xr-x 1 root staff 49 10 6 13:02 pyrealsense2.so -> /usr/local/lib/pyrealsense2.cpython-37m-darwin.so
Python3からimportで確認しています。
% python3
>>> import pyrealsense2
>>> print(pyrealsense2.__version__)
2.34.0
4 コード
作成したコードは、以下の通りです。
一定の距離で背景を取り除く処理は、Pythonラッパーのサンプルコードで提供されている、Stream Alignmentを参考にさせて頂きました。
IntelRealSense/librealsense/wrappers/python/examples/align-depth2color.py
# -*- coding: utf-8 -*-
import pyrealsense2 as rs
import numpy as np
import cv2
WIDTH = 640
HEIGHT = 480
# ストリーミング初期化
config = rs.config()
config.enable_stream(rs.stream.color, WIDTH, HEIGHT, rs.format.bgr8, 30)
config.enable_stream(rs.stream.depth, WIDTH, HEIGHT, rs.format.z16, 30)
# ストリーミング開始
pipeline = rs.pipeline()
profile = pipeline.start(config)
# 距離[m] = depth * depth_scale
depth_sensor = profile.get_device().first_depth_sensor()
depth_scale = depth_sensor.get_depth_scale()
clipping_distance_in_meters = 0.4 # 40cm以内を検出
clipping_distance = clipping_distance_in_meters / depth_scale
# Alignオブジェクト生成
align_to = rs.stream.color
align = rs.align(align_to)
threshold = (WIDTH * HEIGHT * 3) * 0.95
try:
while True:
frames = pipeline.wait_for_frames()
aligned_frames = align.process(frames)
color_frame = aligned_frames.get_color_frame()
depth_frame = aligned_frames.get_depth_frame()
if not depth_frame or not color_frame:
continue
color_image = np.asanyarray(color_frame.get_data())
depth_image = np.asanyarray(depth_frame.get_data())
# clipping_distance_in_metersm以内を画像化
white_color = 255 # 背景色
depth_image_3d = np.dstack((depth_image, depth_image, depth_image))
bg_removed = np.where((depth_image_3d > clipping_distance) | (depth_image_3d <= 0), white_color, color_image)
# 背景色となっているピクセル数をカウント
white_pic = np.sum(bg_removed == 255)
# 背景色が一定値以下になった時に、「検出」を表示する
if(threshold > white_pic):
print("検出 {}".format(white_pic))
else:
print("{}".format(white_pic))
images = np.hstack((bg_removed, color_image))
cv2.imshow('Frames', images)
if cv2.waitKey(1) & 0xff == 27:
break
finally:
# ストリーミング停止
pipeline.stop()
cv2.destroyAllWindows()
5 最後に
今回は、D435iで近くに来た物体だけを抽出してみました。こちらの方法だと、不要な背景を取り除けるのがメリットかも知れません。