
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なら表示はできません。
それではまた。






LEAVE A REPLY