この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
1 はじめに
CX事業本部の平内(SIN)です。
今回は、Jetson Nano上で、インテル® RealSense の画像を処理する(今回は、表示しているだけ)と同時に、Kinesis Video Streamsに送信する要領を確認してみました。
2 構成
構成は、以下のようなイメージです。
- インテル® RealSense の画像は、pyrealsense2でPythonスクリプトに取り込みます
- OpenCVは、GStreamerを入出力IOとして利用できるように構成します
- GStreamerは、ソースをappsrc、シンクをkvssinkとして構成します
- pyrealsense2から受け取った画像は、OpenCVのVideoWriterでGStreamerへ出力します
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_PYTHON_BINDINGS:bool=true -DPYTHON_EXECUTABLE=/usr/bin/python3
$ make -j4
$ sudo make install
$ export PYTHONPATH=$PYTHONPATH:/usr/local/lib
途中CMakeが、「The Xinerama headers were not found」で止まってしまったので下記を追加しました。
$ sudo apt-get install libsdl2-dev
Pythonから利用可能になっているようすです。
$ python3
Python 3.6.9 (default, Oct 8 2020, 12:12:24)
[GCC 8.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pyrealsense2.pyrealsense2 as rs
>>> rs.__version__
'2.42.0'
>>>
4 OpenCVのVideo I/O
JetPackでセットアップされたOpenCVは、ビデオ入出力で、GStreamer:YES (1.14.5) となっているので、そのまま利用可能です
$ python3
Python 3.6.9 (default, Oct 8 2020, 12:12:24)
[GCC 8.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> print(cv2.getBuildInformation())
General configuration for OpenCV 4.1.1 =====================================
Version control: 4.1.1-2-gd5a58aa75
Platform:
Timestamp: 2019-12-13T17:25:11Z
Host: Linux 4.9.140-tegra aarch64
CMake: 3.10.2
CMake generator: Unix Makefiles
CMake build tool: /usr/bin/make
Configuration: Release
・・・略・・・
Video I/O:
FFMPEG: YES
avcodec: YES (57.107.100)
avformat: YES (57.83.100)
avutil: YES (55.78.100)
swscale: YES (4.8.100)
avresample: NO
GStreamer: YES (1.14.5)
v4l/v4l2: YES (linux/videodev2.h)
5 GStreamer
GStreamerでは、入力(appsrc)と出力(appsink)にOpenCVを使用する事ができます。
OpenCVとGStreamerの連携は、概ね以下の通りです。
ソースをappsrcとし、kvssinkまでのパイプラインを、そのまま、OpenCVの VideoWriter() に設定します。 送信するフレームは、VideoWriterオブジェクトに write(frame) するだけです。
GSTERAMER = 'appsrc ! パイプライン ! kvssink'
out = cv2.VideoWriter(GSTERAMER, cv2.CAP_GSTREAMER, 0, fps, (width, height), True)
out.write(frame);
6 コード
Jetson Nano上で動作しているコードです。
pyrealsense2から受け取ったオブジェクトをOpenCVで扱うためには、numpy arrayに変換が必要です。
# -*- coding: utf-8 -*-
import pyrealsense2.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)
GSTERAMER = 'appsrc ! videoconvert ! nvvidconv ! nvv4l2h264enc ! h264parse ! video/x-h264,stream-format=avc,alignment=au,profile=baseline ! kvssink stream-name=Sample000 storage-size=512 access-key=xxxxxxxx secret-key=xxxxxxxxxxxxxxxx aws-region=ap-northeast-1'
try:
out = cv2.VideoWriter(GSTERAMER, cv2.CAP_GSTREAMER, 0, 15, (640, 480), True)
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())
depth_image = cv2.applyColorMap(cv2.convertScaleAbs(depth_image, alpha=0.08), cv2.COLORMAP_JET)
out.write(color_image)
cv2.imshow('color_image', color_image)
cv2.imshow('depth_image', depth_image)
if cv2.waitKey(1) & 0xff == 27:
break
finally:
pipeline.stop()
cv2.destroyAllWindows()
7 最後に
今回は、Jetson Nanoでインテル® RealSense の画像をKinesis Video Streamsに送ってみました。 OpenCVをGStreamerのソースとして扱うと、動画処理の自由度が広がると思います。