2025.09.30

Jetson × RealSense で物体検知: ROS 2 / DeepStream の導入

はじめに

こんにちは。グループ研究開発本部、AI研究開発室のY.Tです。
エッジGPU、良い響きですね。
この記事は、Jetson への DeepStream 7.1 を導入と、Intel RealSense の接続方法について備忘録的にまとめたものです。とりあえず何か画面に見えるまで1からやるとそれなりに手間がかかったので、一旦まとめておこうという書いています。

今回の目的

  • 前提: Jetson (Orin Nano Super, JetPack 6.x 相当)・RealSense D435i・ROS 2 Humble
  • 今回の目的: RealSense RGB → deepstream-app → 人/車/標識/二輪の4クラス検出 → 画面表示

環境

  • JetPack 6.x (Ubuntu 22.04 aarch64)
  • DeepStream 7.1 (Jetson 版)
  • Intel RealSense D435i
  • ROS 2 Humble

1) 前提のインストール

ROS 2 Humble

こちらを参考にインストールします。
ROS 2 Documentation: Humble Installation Ubuntu (deb packages)
自分の手順は以下のような形です。

sudo apt install -y locales software-properties-common curl
sudo locale-gen en_US en_US.UTF-8 && sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
source /etc/default/locale || true

# ROS 2 APTソース指定
export ROS_APT_SOURCE_VERSION=$(curl -s https://api.github.com/repos/ros-infrastructure/ros-apt-source/releases/latest | grep -F "tag_name" | awk -F\" '{print $4}')
curl -L -o /tmp/ros2-apt-source.deb "https://github.com/ros-infrastructure/ros-apt-source/releases/download/${ROS_APT_SOURCE_VERSION}/ros2-apt-source_${ROS_APT_SOURCE_VERSION}.$(. /etc/os-release && echo $VERSION_CODENAME)_all.deb"
sudo dpkg -i /tmp/ros2-apt-source.deb

sudo apt update
sudo apt install -y ros-humble-desktop python3-rosdep
source /opt/ros/humble/setup.bash

# ワークスペースを作成しておく
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws
rosdep init || true
rosdep update

DeepStream 7.1

SDK Manager で導入済みなら本章はスキップ可。 ここでは アーカイブ版(tbz2) の手動導入を記載します。

# パッケージを展開(例:Downloads に置いた tbz2 を /opt へ)
sudo mkdir -p /opt/nvidia/deepstream
cd ~/Downloads
sudo tar -xvf deepstream_sdk_v7.1.0_jetson.tbz2 -C /opt/nvidia/deepstream/

# インストーラ実行
cd /opt/nvidia/deepstream/deepstream-7.1
sudo ./install.sh
sudo ldconfig

# 環境変数を設定しておく
echo 'export GST_PLUGIN_PATH=/opt/nvidia/deepstream/deepstream-7.1/lib/gst-plugins:$GST_PLUGIN_PATH' | sudo tee -a /etc/environment
echo 'export LD_LIBRARY_PATH=/opt/nvidia/deepstream/deepstream-7.1/lib:$LD_LIBRARY_PATH' | sudo tee -a /etc/environment
source /etc/environment
export GST_PLUGIN_PATH=/opt/nvidia/deepstream/deepstream-7.1/lib/gst-plugins:$GST_PLUGIN_PATH
export LD_LIBRARY_PATH=/opt/nvidia/deepstream/deepstream-7.1/lib:$LD_LIBRARY_PATH

2) RealSense(librealsense)

realsense-viewerを使えるようにしておく。ターミナルからrealsense-viewerを叩くとGUIが起動し、GUIを操作することでリアルタイムにカメラの映像が流れるようになる。今回は使わないがDepthも出せる。

sudo apt update && sudo apt install -y git cmake build-essential libssl-dev \
  libusb-1.0-0-dev pkg-config libgtk-3-dev libglfw3-dev libgl1-mesa-dev libglu1-mesa-dev udev
git clone --depth=1 https://github.com/IntelRealSense/librealsense.git

cd librealsense && mkdir build && cd build
cmake .. -DFORCE_RSUSB_BACKEND=ON -DBUILD_WITH_CUDA=ON -DBUILD_EXAMPLES=OFF -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)
sudo make install

sudo cp ../config/99-realsense-libusb.rules /etc/udev/rules.d/
sudo udevadm control --reload-rules && sudo udevadm trigger

realsense-viewer   # GUIが起動する。RGB が映ればOK

3)DeepStreamのサンプル実行

サンプルconfigをユーザ領域へ複製して編集すると扱いやすい。(設定ファイル内のファイルの参照は相対パスなのでそこは注意。)今回はsource2_1080p_dec_infer-resnet_demux_int8.txtというファイル名のconfigで動かす。サンプル動画もパッケージに含まれている。

mkdir -p ~/ds_cfg
cd /opt/nvidia/deepstream/deepstream-7.1/samples/configs/deepstream-app
cp source2_1080p_dec_infer-resnet_demux_int8.txt ~/ds_cfg/
cp -a ../../models/Primary_Detector ~/ds_cfg/  # 参照しやすい場所に置く(任意)

# 表示を有効化(sink0=EGL)と mux バッチを 2 に統一、URI を絶対化
APP=~/ds_cfg/source2_1080p_dec_infer-resnet_demux_int8.txt
xhost +local: 2>/dev/null || true
export DISPLAY=${DISPLAY:-:0}
sed -i '/^\[sink0\]/,/^\[/{s/^type=.*/type=2/; s/^enable=.*/enable=1/; s/^sync=.*/sync=0/}' "$APP"
sed -i '/^\[sink1\]/,/^\[/{s/^enable=.*/enable=0/}' "$APP"
sed -i '/^\[sink2\]/,/^\[/{s/^enable=.*/enable=0/}' "$APP"
sed -i '/^\[streammux\]/,/^\[/{s/^batch-size=.*/batch-size=2/}' "$APP"
sed -i 's#uri=file://\./\./streams/#uri=file:///opt/nvidia/deepstream/deepstream-7.1/samples/streams/#g' "$APP"

3-1) TensorRT エンジン作成

アプリケーションの初回実行時に作成されてキャッシュに保存され、次回以降はキャッシュを参照して高速に起動する。。。はずではあるが、うまくキャッシュを保存できない、読めない、という状況なら明示的に作ってしまうのが早いです。

mkdir -p ~/.cache/ds_engines
/usr/src/tensorrt/bin/trtexec \
  --onnx=/opt/nvidia/deepstream/deepstream-7.1/samples/models/Primary_Detector/resnet18_trafficcamnet_pruned.onnx \
  --int8 --calib=/opt/nvidia/deepstream/deepstream-7.1/samples/models/Primary_Detector/cal_trt.bin \
  --minShapes='input_1:0':1x3x544x960 --optShapes='input_1:0':2x3x544x960 --maxShapes='input_1:0':2x3x544x960 \
  --memPoolSize=workspace:2048M \
  --saveEngine=$HOME/.cache/ds_engines/primary_b2_gpu0_int8.engine

3-2) P‑GIEのconfigを編集

~/ds_cfg/config_infer_primary.txt を新規作成し、シンプルに必要な項目だけ書く。

[property]
gpu-id=0
net-scale-factor=0.0039215697906911373
offsets=123.0;117.0;104.0
model-engine-file=%HOME%/.cache/ds_engines/primary_b2_gpu0_int8.engine
onnx-file=/opt/nvidia/deepstream/deepstream-7.1/samples/models/Primary_Detector/resnet18_trafficcamnet_pruned.onnx

labelfile-path=/opt/nvidia/deepstream/deepstream-7.1/samples/models/Primary_Detector/labels.txt
int8-calib-file=/opt/nvidia/deepstream/deepstream-7.1/samples/models/Primary_Detector/cal_trt.bin
network-mode=1
batch-size=2

custom-lib-path=/opt/nvidia/deepstream/deepstream-7.1/lib/libnvds_infercustomparser.so
parse-bbox-func-name=NvDsInferParseCustomResnet
output-blob-names=output_cov/Sigmoid;output_bbox/BiasAdd
num-detected-classes=4
gie-unique-id=1

[class-attrs-all]
pre-cluster-threshold=0.20
nms-iou-threshold=0.5
cluster-mode=2
topk=200

注意model-engine-fileの参照はよく確認すること

sed -i 's#^model-engine-file=.*#model-engine-file='"$HOME"'/.cache/ds_engines/primary_b2_gpu0_int8.engine#' ~/ds_cfg/config_infer_primary.txt

アプリ側config($APP)で P‑GIE をこのファイルに差し替える。

sed -i "s#^config-file=./dstest1_pgie_config.txt#config-file=$HOME/ds_cfg/config_infer_primary.txt#" "$APP"

3-3) 実行

engineファイルを作成済みなので高速に起動するはず。起動に数分以上かかるようならTensorRTエンジンを再作成しているはずで、cacheを参照できていない。単純にパスが違うケースもあるが、設定ファイルの記述の不整合の場合もある。以下に動画のように検知ボックスが出てこないケースでは、モデルが違うか、config_infer_primary.txtの閾値の問題の場合もあります。

/opt/nvidia/deepstream/deepstream-7.1/bin/deepstream-app -c "$APP"

4) ROS 2 でRealSenseを動かす(任意)

RealSense の ROS 2 ノードで軽量に RGB を配信しつつ可視化する例。自分は十分なFPSを得るためにROS2を導入しました。
ちなみに、GUIが起動したら、GUI上で見たいトピックを選択しないと画面は真っ黒です。そんな事で困る人はあまりいないかもしれませんが念の為(一敗)。

ROS_DISTRO=humble
source /opt/ros/$ROS_DISTRO/setup.bash
. ~/ros2_ws/install/setup.bash
ros2 run realsense2_camera realsense2_camera_node --ros-args \
  -p enable_color:=true -p enable_depth:=false -p enable_infra1:=false -p enable_infra2:=false \
  -p enable_gyro:=false -p enable_accel:=false \
  -p rgb_camera.color_profile:="424x240x15" \
  -p rgb_camera.frames_queue_size:=2 -p color_qos:=SENSOR_DATA -p initial_reset:=true

# 可視化(GUIが起動。)
ros2 run rqt_image_view rqt_image_view

5) 今回のハマりどころ

DeepStream が「動いてるっぽいのに出ない」とき、結局よくハマるのはこのあたりです。参考になれば。

エンジン(.engine)の置き場所

思ったファイルを参照できていないのはよくやらかしますね。例えば、既定で /opt/... に吐こうとして 書き込めない パターンなど、、、
ユーザ領域のわかりやすいところに自分でディレクトリを作ってちゃんと設定するのが安定ですね。(例:~/.cache/ds_engines/primary_b2_gpu0_int8.engine)。何参照してるかわからないならば、いったん消して作り直すのが手っ取り早いです。

TensorRT の世代が合ってない

別環境から持ち込んだ .engine をそのまま使ったときに起きがちですね。TensorRT のバージョン違いでロード直後に落ちたり、推論が始まらないなど。
解決策はシンプル、現環境で再生成です。再ビルドしてコーヒーでも飲んでいましょう。

batch が噛み合ってない

  • streammuxbatch-size と P-GIE の batch-size同じか確認。
  • エンジンは他のbatch設定で使えないので、値を変えたらエンジンも作り直し。

パーサと出力名がモデルに合ってない

推論は回ってるのに検出ゼロ、のケースでよくあリマス。

parse-bbox-func-name=NvDsInferParseCustomResnet
output-blob-names=output_cov/Sigmoid;output_bbox/BiasAdd

ResNet10(dstest1 系)は上記で確認。BatchedNMS/TLT 系を混ぜると出力数が合わなくて沈黙します。

実は OSD / sink で消してる

ログでは検出カウントが増えてるのに画面は無、という時はこの辺りを疑いましょう。

  • [osd]enable=1 display-bbox=1 display-text=1 になってる?
  • [sink0]nveglglessink など表示系になってる?(fakesink は見えません)

閾値が高すぎる

一時的に思い切って下げて実行してみるとわかります。暗い/小さい被写体は特に注意

sed -i 's/^pre-cluster-threshold=.*/pre-cluster-threshold=0.15/' ~/ds_cfg/config_infer_primary.txt

まとめ

以上、とりあえず環境構築でした。次はカメラ映像での検知モデル実行の予定です。

宣伝

グループ研究開発本部 AI研究開発室では、データサイエンティスト/機械学習エンジニアを募集しています。ビッグデータの解析業務などAI研究開発室にご興味を持って頂ける方がいらっしゃいましたら、ぜひ 募集職種一覧 からご応募をお願いします。皆さんのご応募をお待ちしています。

  • Twitter
  • Facebook
  • はてなブックマークに追加

グループ研究開発本部の最新情報をTwitterで配信中です。ぜひフォローください。

 
  • AI研究開発室
  • 大阪研究開発グループ

関連記事