Jetson NanoでUSBカメラのYOLO12リアルタイム物体検出を表示+保存する方法(Docker+SSH対応)

Jetson NanoでUSBカメラのYOLO12リアルタイム物体検出を表示+保存する方法(Docker+SSH対応)

Jetson NanoでYOLOを動かすところまではできても、次で詰まりがちです。

  • USBカメラの映像でリアルタイム推論したい
  • Jetsonのモニタに“推論ウィンドウ”を表示したい
  • 同時にAVI動画として保存もしたい
  • しかも SSH接続で作業したい(PCから操作したい)

この記事では、上の要件を全部満たす「最短の再現手順」をまとめます。
ポイントは DockerにUSBカメラを渡すことと、コンテナがOpenCV “GUI対応” であることです。

環境構築を紹介した記事はこちらです。

この記事のゴール

最終的に、Jetson側で次を実現します。

  • USBカメラ(/dev/video0)を入力にYOLO12推論
  • Jetsonのモニタに推論ウィンドウ表示(リアルタイム)
  • 同時に 0.avi を保存
  • 実行は Jetson端末でもSSHでもOK(表示はJetsonモニタに出る)

前提環境

  • Jetson Nano(JetPack4系を想定)
  • Ubuntu 18.04系
  • Docker が動作している
  • USBカメラ(UVCカメラ)接続
  • Jetsonにモニタ接続(GUIログイン済み)

1.JetsonでUSBカメラが見えるか確認

SSHでJetsonに接続して確認します。

ls -l /dev/video*

例:/dev/video0 が見えればOK。

2.Dockerが動いているか確認

sudo systemctl status docker --no-pager

Active (running) ならOK。

3.YOLOコンテナを起動してUSBカメラを渡す

JetPack4向けのタグを使います(例)。

sudo docker images | head

すでに ultralytics/ultralytics:latest-jetson-jetpack4 があるならそれで進めます。
(無ければ sudo docker pull ...

コンテナ起動(ここが重要):

sudo docker run -it --rm \
  --runtime nvidia \
  --network host \
  --device /dev/video0:/dev/video0 \
  ultralytics/ultralytics:latest-jetson-jetpack4

コンテナ内で /dev/video0 が見えるか確認:

ls -l /dev/video*

4.まず「保存」はできる(AVIができれば推論自体は成功)

表示はあとで整えます。まず保存ができれば、入力~推論の流れはOKです。

yolo predict model=yolo12n.pt source=0 imgsz=320 save=True

保存先(コンテナ内の例):

ls -lah runs/detect/predict

0.avi ができていれば推論は成功です。

5.なのに “show=True” でウィンドウが出ない理由

ここが最大の落とし穴です。

コンテナがOpenCV “headless(GUIなし)” だと、show=True でもウィンドウは絶対に出ません。

確認コマンド:

  • python3 – <<‘PY’
  • import cv2
  • info = cv2.getBuildInformation().lower()
  • print(“has gtk:”, (“gtk” in info))
  • print(“has qt :”, (“qt” in info))
  • PY

has gtk: False / has qt: False → GUI無し → 表示不可

私のケースも最初ここに当たっていました。

6.コンテナをGUI表示できるように直す(OpenCVをGUI対応に)

コンテナ内で opencv-python(GUIあり)を入れます。
opencv-python-headless ではありません)

python3 -m pip uninstall -y opencv-python opencv-python-headless || true
python3 -m pip install --no-cache-dir opencv-python

さらにQt/X11系の依存を入れておくと安定します:

apt-get update
apt-get install -y \
  libglib2.0-0 libsm6 libxext6 libxrender1 \
  libgtk2.0-0 libgtk-3-0 \
  libcanberra-gtk-module libcanberra-gtk3-module

そしてGUI対応になったか確認:

python3 - <<'PY'
import cv2
info = cv2.getBuildInformation().lower()
print("has gtk:", ("gtk" in info))
print("has qt :", ("qt" in info))
PY

7.SSHから起動しても「Jetsonモニタに表示」する(X11の渡し方)

表示をJetson側モニタに出すには、ホスト側でX11を許可して、DockerにXソケットを渡します。

7-1. Jetsonホスト側でX11許可(ホストで実行)

export DISPLAY=:0
xhost +local:root

Jetsonは GUIログイン済みであること(デスクトップが出ている状態)。

7-2. X11を渡してDocker起動(ホストで実行)

sudo docker run -it --rm \
  --runtime nvidia \
  --network host \
  --device /dev/video0:/dev/video0 \
  -e DISPLAY=:0 \
  -v /tmp/.X11-unix:/tmp/.X11-unix \
  ultralytics/ultralytics:latest-jetson-jetpack4

7-3. OpenCVのテストウィンドウ(コンテナ内)

まずこれで小窓が出るか確認(2秒):

python3 - <<'PY'
import cv2, numpy as np
img=np.zeros((240,320,3),dtype=np.uint8)
cv2.putText(img,'opencv window OK',(10,120),cv2.FONT_HERSHEY_SIMPLEX,0.7,(0,255,0),2)
cv2.imshow('test', img)
cv2.waitKey(2000)
cv2.destroyAllWindows()
PY

これがJetsonモニタに出れば、YOLOも出ます。

8.リアルタイム表示+保存を同時に行う(コンテナ内)

yolo predict model=yolo12n.pt source=0 imgsz=320 show=True save=True
  • 表示:Jetsonモニタに推論ウィンドウ
  • 保存:0.avi などが出力

9.変更が消える問題(超重要):毎回ウィンドウが出なくなる理由

ここも初心者が詰まるポイントです。

Dockerを --rm で起動していると、コンテナ終了と同時に状態が消えます。
つまり、コンテナ内でOpenCVをGUI対応に直しても、次回起動で元通り → また表示できない、が起こります。

解決策は2つあります。

  • GUI対応にした状態をcommitして新しいイメージにする(おすすめ)
  • 毎回コンテナ内で再インストール(非推奨)

10. GUI対応済みイメージを作って固定化する(docker commit)

10-1. “保存用”にコンテナを --rm なしで起動

ホスト側で:

sudo docker run -it \
  --name yolo_gui \
  --runtime nvidia \
  --network host \
  --device /dev/video0:/dev/video0 \
  -e DISPLAY=:0 \
  -v /tmp/.X11-unix:/tmp/.X11-unix \
  ultralytics/ultralytics:latest-jetson-jetpack4 \
  bash

コンテナ内でOpenCV GUI対応を入れる(前述の手順)。

10-2. ホスト側でcommit

別ターミナル(ホスト側)で:

sudo docker commit yolo_gui ultralytics/ultralytics:jetpack4-gui
sudo docker rm -f yolo_gui

これで ultralytics/ultralytics:jetpack4-gui が **“表示できるYOLO環境”**として固定化されます。

11.最終形:Jetsonで「表示+保存」を1発で実行するスクリプト

11-1. 出力をホストに残す(保存が消えない)

ホストに保存フォルダを作ります。

mkdir -p /home/ai/yolo_out

11-2. 1発スクリプト(Jetson上に保存)

以下をJetson(SSHでも可)で実行して保存します。

cat > /home/ai/yolo_cam_live.sh <<'SH'
#!/usr/bin/env bash
set -e

IMG="ultralytics/ultralytics:jetpack4-gui"
OUT_DIR="/home/ai/yolo_out"
MODEL="yolo12n.pt"   # engineなら "yolo12n.engine"
SRC="0"
IMGSZ="320"
NAME="cam_live"

mkdir -p "${OUT_DIR}"

export DISPLAY=:0
xhost +local:root >/dev/null

sudo docker run -it --rm \
  --runtime nvidia \
  --network host \
  --device /dev/video0:/dev/video0 \
  -e DISPLAY=:0 \
  -v /tmp/.X11-unix:/tmp/.X11-unix \
  -v "${OUT_DIR}:/ultralytics/runs" \
  "${IMG}" \
  bash -lc "yolo predict model=${MODEL} source=${SRC} imgsz=${IMGSZ} show=True save=True project=/ultralytics/runs name=${NAME} exist_ok=True"
SH

chmod +x /home/ai/yolo_cam_live.sh

11-3. 実行

Jetson側でこれだけ:

/home/ai/yolo_cam_live.sh
  • Jetsonモニタに推論ウィンドウ表示
  • 同時に保存(ホスト側)

/home/ai/yolo_out/detect/cam_live/0.avi

12.保存したAVIをJetsonで再生する

mpv /home/ai/yolo_out/detect/cam_live/0.avi

よくある質問(FAQ)

Q1. SSHだとリアルタイム表示できない?

SSH自体がダメではなく、表示先(DISPLAY)をJetsonのX11に向けて、XソケットをDockerに渡せば表示できます
この記事の xhost-v /tmp/.X11-unix がそれです。

Q2. 途中で「地域(Asia/Tokyo)」を聞かれた

tzdata の設定です。Jetsonなら Asia → Tokyo を選べばOK。
対話を避けたい場合は DEBIAN_FRONTEND=noninteractive を使います。

Q3. “show=True なのに出ない”最大原因は?

ほぼ OpenCVがheadlessです。
has gtk/qt を確認してFalseなら表示はできません。

それではまた。

About The Author

Hideki
東京大学発AIスタートアップ企業でロボット開発室室長、画像解析室室長、動画解析室室長を務め、AIエンジニアとしても画像認識関連の特許を在籍中に3つ取得。その後、KDDIグループ内でプロダクトリーダーとして自然言語処理パッケージの自社開発を経て、現在はAGRISTのテックリードとして農業の人手不足の解決に向けた収穫ロボットの開発にチャレンジしている。ロボットは技術の総合格闘技との考え方から、AIだけでなく、ハードやエレキ、通信からクラウド、IOTまで幅広く手掛けることができる。最近では人とロボットの共存を目指すべく、性能だけを追い求める開発から「感動やワクワク体験」をデザインできるロボットの研究を進めており、人とロボットがうまく共存できる世界を作り出したいと日々行動している。

LEAVE A REPLY

*
*
* (公開されません)