インテル Realsence D435iで、近くに来た物体だけを撮影してみました
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で近くに来た物体だけを抽出してみました。こちらの方法だと、不要な背景を取り除けるのがメリットかも知れません。