AI-Inference, IoT
- Nvidia DLI(Deep Learning Institute) Dockerイメージを使用
libargus
でCSIカメラをコンテナ内から操作- OpenCV with CUDA +
cudaMallocManaged
による zero-copy
- Jupyter notebook 上でOpenCV(Python bind)を呼び出して機能検証
- NVIDIA AIコース履修
- インクリメンタルで軽量な開発
- サンプルを流用し運用向けにセットアップ
-
2GB版
NVIDIA-JETSON-NANO-2GB
-
B01
の廉価版, 6~8千円 -
EOL(製造終了)
NVIDIA does not specify Lifecycle information for Jetson developer kits, which are intended for software development and system prototyping, not production use. Learn more here.
-
代替候補
Jetson Devkit price details Lifecycle Nano B01 Devkit 2~3万円 2022/11~在庫復活 January 2027 Orina Nano 8GB Devkit 6~8万円 AI処理性能が80倍向上 January 2030
-
-
1×MIPI CSI-2 camera connector
- 15pin, 1mm pitch
- TE Connectivity
1-1734248-5
- RaspberryPi互換
-
安価なRaspberry Pi Camera Module準拠品を使う
-
RPi用を謳っているカメラは2データレーン(RPi CM4は4データレーンが有効)
V4L2 driver support Sensor Resolution RPi name No. of Pins Pitch $\times$ (EOL)OmniVision OV5647 2592 × 1944 V1 15pin 1mm ◯ i2c/nv_imx219.c@L4T Sony IMX219 3280 × 2464 V2 15pin 1mm △ 有志作成 Sony IMX708 4608 × 2592 V3 15pin 1mm $\times$ (EOL) binary配布OBISP AR1335 4160 × 3120 非公式 15pin 1mm ◯ i2c/nv_imx477.c@L4T Sony IMX477 4056 x 3040 HQ Camera 22pin 0.5mm -
IMX219 レパートリー (コネクタ品番=
SFW15R-1STE1LF
)Features Camera SKU Wide Angle B0179 Auto Focus B0181 Low Distortion B0183 Low Distortion NoIR B0187 Auto Focus NoIR B0189 Fixed Focus B0191 Wide Angle NoIR B0193 Fisheye lens B0287 NoIR ... IRフィルター無し(=赤外線を拾う)
-
ISP(Image Signal Processor) による debayer
-
RPi は Video Core 4/6 内の非公開IPコア(ThreadX)で処理
- エンヤヒロカズ (2019). コラム『撮影コマンドを実行するのはラズベリー・パイかイメージセンサか』Interface(2019年7月号),118.
-
Nvidia Camera Architecture Stack
- Libargus Camera API経由でカメラ制御、バッファ操作、カメラメタデータ取得
-
The camera architecture includes the following NVIDIA components:
-
libargus
: Provides a low-level API based on the camera core stack. -
nvarguscamerasrc
: NVIDIA camera GStreamer plugin that provides options to control ISP properties using the ARGUS API. -
v4l2src
: A standard Linux V4L2 application that uses direct kernel IOCTL calls to access V4L2 functionality.
-
-
-
応用) 高速度撮影: Jetson Nano V4L2 driver modifications to add a 640x480 200FPS mode for the Sony IMX219
-
IMX219で赤外線LED付きのものを購入
64GB以上推奨
-
JetPack 4.6.1 for Jetson Nano 2GB (L4T 32.7.1)
- jetson-nano-2gb-jp46-sd-card-image.zip
- JetPack 4.6がNano/TX1/TX2向け最後のメジャーリリース
- JetPack 5.x以降はXavierとOrinのみサポート
- jetson-nano-2gb-jp46-sd-card-image.zip
-
Swap 領域を10G確保
sudo swapoff -a sudo systemctl disable nvzramconfig sudo dd if=/dev/zero of=/swapfile bs=1M count=10240 sudo mkswap /swapfilesudo su sudo swapon -p 1 /swapfile
cat /proc/device-tree/tegra-camera-platform/modules/module0/drivernode0/proc-device-tree/proc/device-tree/cam_i2cmux/i2c@0/rbpcv2_imx219_a
- 参考: gstreamer pipeline例@Qiita
L4T(Linux for Tegra)のパッケージ提供されるOpenCVはCUDA非対応。 OpenCV with CUDAで構築済のDocker環境を利用する。
- L4Tのバージョンに合致するDockerイメージを指定すること
/etc/nv_tegra_release
:r32.7.1
nvcr.io/nvidia/dli/dli-nano-ai:v2.0.2-r32.7.1ja
nvcr.io/nvidia/dli/dli-nano-ai:v2.0.2-r32.7.1ja
NVIDIA 学習コース用
Container for DLI Getting Started with AI on Jetson Nano
This container is used in the NVIDIA Deep Learning Institute course Getting Started with AI on Jetson Nano and should be run on an NVIDIA Jetson Nano. This course is also an element of the Jetson AI Fundamentals and the Jetson AI Certification Program. If you have not done so yet, we highly recommend you take the full free course, and check out other self-paced online courses and instructor-led workshops available from the NVIDIA Deep Learning Institute.
#!/bin/bash -eu
DOCKER_IMG=nvcr.io/nvidia/dli/dli-nano-ai:v2.0.2-r32.7.1ja
sudo docker run -it --rm --runtime nvidia \
--net=host --memory=500M --memory-swap=8G \
--device /dev/video0 \
-v /tmp/argus_socket:/tmp/argus_socket \
-v ${PWD}:/nvdli-nano/data \
${DOCKER_IMG}
- Jupyter notebook: http://localhost:8080
- password:
dlinano
l4t-ml:r32.7.1-py3
l4t-ml:r32.7.1-py3
Get started on your AI journey quickly on Jetson. The Machine learning container contains TensorFlow, PyTorch, JupyterLab, and other popular ML and data science frameworks such as scikit-learn, scipy, and Pandas pre-installed in a Python 3.6 environment.
sudo docker pull nvcr.io/nvidia/l4t-ml:r32.7.1-py3
https://catalog.ngc.nvidia.com/orgs/nvidia/containers/l4t-ml
contains:
- TensorFlow 1.15.5
- PyTorch v1.10.0
- torchvision v0.11.0
- torchaudio v0.10.0
- onnx 1.11.0
- CuPy 9.2.0
- numpy 1.19.5
- numba 0.53.1
- OpenCV 4.5.0 (with CUDA)
- pandas 1.1.5
- scipy 1.5.4
- scikit-learn 0.24.2
- JupyterLab 2.2.9
OpenCV with CUDA
$ python3
>>> import cv2
>>> print(cv2.__version__)
4.5.0
>>> print(cv2.getBuildInformation())
General configuration for OpenCV 4.5.0 =====================================
...
NVIDIA CUDA: YES (ver 10.2, CUFFT CUBLAS FAST_MATH)
NVIDIA GPU arch: 53 62 72
NVIDIA PTX archs:
...
Jupyter notebook 上にCSIカメラからの動画を描画してみる
Dockerイメージ nvidia/l4t-ml:r32.7.1-py3
を起動
#!/bin/bash -eu
DISPLAY=:0
DOCKER_IMG=nvcr.io/nvidia/l4t-ml:r32.7.1-py3
/usr/bin/env -i DISPLAY=${DISPLAY} /usr/bin/xhost +si:localuser:root
sudo docker run -it --rm --net=host --runtime nvidia \
--memory=500M --memory-swap=8G \
--device /dev/video0 \
-e DISPLAY=${DISPLAY} \
-v /tmp/.X11-unix/:/tmp/.X11-unix \
-v /tmp/argus_socket:/tmp/argus_socket \
-v ${PWD}:/data \
${DOCKER_IMG}
- Jupyter notebook: http://localhost:8080
- password:
nvidia
notebook のpythonセルにコードを記述して実行
import cv2
import numpy as np
from PIL import Image
import io
import IPython
# CSI camera 640x480 30fps
def cameraCSI():
GST_STR = "nvarguscamerasrc sensor-id=0 ! \
video/x-raw(memory:NVMM), width=(int)640, height=(int)480, format=(string)NV12, framerate=(fraction)30/1 ! \
nvvidconv ! \
video/x-raw, width=(int)640, height=(int)480, format=(string)BGRx ! \
videoconvert ! \
appsink max-buffers=1 drop=true"
return cv2.VideoCapture(GST_STR, cv2.CAP_GSTREAMER)
def displayInJupyter(imgBGR, tableGamma) -> None:
arr = io.BytesIO()
# BGR to RGB > apply gamma correction > jpeg array
Image.fromarray(cv2.LUT(cv2.cvtColor(imgBGR, cv2.COLOR_BGR2RGB), tableGamma)).save(arr, 'jpeg')
IPython.display.display(IPython.display.Image(data=arr.getvalue()))
IPython.display.clear_output(wait=True)
# Build a lookup table mapping the pixel values [0, 255] to their adjusted gamma values
def tblGamma(gamma):
invGamma = 1.0 / gamma
return np.array([((i / 255.0) ** invGamma) * 255
for i in np.arange(0, 256)]).astype("uint8")
try:
tableGamma = tblGamma(1.5)
cam = cameraCSI()
while(True):
success, frame = cam.read()
if (success):
displayInJupyter(frame, tableGamma)
except KeyboardInterrupt:
print('Stream stopped')
cam.release()
人物特定のための学習 l4t-ml
docker image
git clone --recursive https://github.com/dusty-nv/jetson-inference
cd jetson-inference
git switch L4T-R32.7.1
-
#!/bin/sh env -i DISPLAY=:0 sudo xhost +si:localuser:root ./docker/run.sh \ -v $PWD/python/examples:/jetson-inference/python/examples \ --run python/examples/detectnet-snap.py --log-level=warning \ --threshold=0.9 --input-height=720 --input-width=1280 \ --input-rate=1 --input-flip=horizontal \ csi://0
-
初回セットアップ時に以下のデータ取得処理が走るので注意
- Dockerイメージ
dustynv/jetson-inference:r32.7.1
- 学習済み分類器・モデル
- Dockerイメージ
-
jetson-inference/data
(stores the network models, serialized TensorRT engines, and test images)jetson-inference/python/training/classification/data
(stores classification training datasets)jetson-inference/python/training/classification/models
(stores classification models trained by PyTorch)jetson-inference/python/training/detection/ssd/data
(stores detection training datasets)jetson-inference/python/training/detection/ssd/models
(stores detection models trained by PyTorch)
-
事前学習モデル一覧 → Deploying Deep Learning
- DockerホストのXディスプレイサーバーへUNIXドメインソケットを経由してウィンドウ表示
gdm3(8)
のautologinにより、一般ユーザーでXサーバーDISPLAY=:0
を確保している- コンテナ内PIDがrootにマッピングされてしまう(
podman(1)
なら...) xhost(1)
でコンテナからのXプロトコルを受け付けるように認証を通す必要がある
--device /dev/video0
でホストのデバイスノードをコンテナ内に生やす/tmp/argus_socket
をボリュームマウントgstreamer(3)
のnvarguscamerasrc
オプションからJetson ISP(Image Signal Processor)を介してカメラを調整
ライブカメラを用いた物体検出デモを流用
-
python/examples/detectnet-snap.py
- 検出した物体の切り出しを行う
- 本体はdetectnet.py
- デフォルトでは
ssd-mobilenet-v2
事前学習モデルを使用
-
検出した物体の領域をjpgとして切取る → 人物のみに修正
-
.jpg
保存先を変更 -
JPG形式, 非可逆圧縮
cv2.imwrite(path, image, [int(cv2.IMWRITE_JPEG_QUALITY), quality])
$0 <= quality <= 100$ - OpenCVのデフォルト
$quality=95$
-
PNG形式, 可逆圧縮
cv2.imwrite(path, image, [int(cv2.IMWRITE_PNG_COMPRESSION), compression])
ai-camera.service
# Pre-requisite) USB storage mount entry must be added to /etc/fstab
# UUID=875E-D851 /home/tono/jetson-inference/python/examples/mnt auto user,umask=000,utf8 0 0
[Unit]
Description=AI camera
After=multi-user.target display-manager.service
Requires=display-manager.service
[Service]
Type=simple
Restart=on-failure
RestartSec=3
TimeoutSec=300
StartLimitInterval=600
StartLimitBurst=10
StandardInput=null
StandardOutput=journal
WorkingDirectory=/home/tono/jetson-inference
Environment="CONTAINER_NAME=ai-camera"
Environment="CONTAINER_IMAGE=dustynv/jetson-inference:r32.7.1"
Environment="MNT=./python/examples/mnt"
Environment="DISPLAY=:0"
ExecStartPre=/usr/bin/env -i DISPLAY=${DISPLAY} /usr/bin/xhost +si:localuser:root
ExecStartPre=/bin/mount ${MNT}
Environment="DOCKER_ROOT=/jetson-inference"
Environment="CLASSIFY_DIR=python/training/classification"
Environment="DETECTION_DIR=python/training/detection/ssd"
ExecStart=/bin/docker run --runtime nvidia -it --rm \
--name ${CONTAINER_NAME} \
--network host \
--device /dev/video0 \
-e DISPLAY=${DISPLAY} \
-v /tmp/.X11-unix/:/tmp/.X11-unix \
-v /tmp/argus_socket:/tmp/argus_socket \
-v /etc/enctune.conf:/etc/enctune.conf \
-v $PWD/python/examples:/jetson-inference/python/examples \
-v $PWD/data:$DOCKER_ROOT/data \
-v $PWD/$CLASSIFY_DIR/data:$DOCKER_ROOT/$CLASSIFY_DIR/data \
-v $PWD/$CLASSIFY_DIR/models:$DOCKER_ROOT/$CLASSIFY_DIR/models \
-v $PWD/$DETECTION_DIR/data:$DOCKER_ROOT/$DETECTION_DIR/data \
-v $PWD/$DETECTION_DIR/models:$DOCKER_ROOT/$DETECTION_DIR/models" \
${CONTAINER_IMAGE} \
python/examples/detectnet-snap.py \
--log-level=warning --overlay=none \
--threshold=0.8 --input-height=720 --input-width=1280 \
--input-rate=1 --input-flip=horizontal csi://0
ExecStop=/usr/bin/docker stop -t 5 ${CONTAINER_NAME}
[Install]
WantedBy=multi-user.target
- サービス有効化&開始:
sudo systemctl enable ai-camera && sudo systemctl start ai-camera
-
USBフラッシュメモリ(FAT32)のディレクトリ内最大ファイル数 → 64K上限
-
日毎に
tar(1)
で固める処理を1時間おきにcron(8)
からバッチ実行して追記#!/bin/sh cd /home/tono/jetson-inference/python/examples/mnt/ && \ ls -1 *.jpg 2>/dev/null | xargs -I % sh -c 'ym=`echo % | \ sed -ne "s/^\([0-9]\{8\}\)-.*/\1/p"`; tar -rf ${ym}.tar % && rm -f %'
-
検証:
sudo run-parts --test /etc/cron.hourly
- 再起動時のアプリケーション自動起動 → OK
- NTPから現在時刻を取得できないため、RTCモジュールを追加しなければならない
- UPS代わりにモバイルバッテリを使用して解消
調査,ネタ
下記無料コースを受講(NVIDIAアカウント登録)して習得
姿勢推定 trt_pose
python3 -m pip install --upgrade pip
python3 -m pip install tqdm pycocotools
ハンドサイン認識 trt_pose_hand
- ocnn: エッジデバイス向け推論エンジン
- 主にAndroid/iOSをターゲットとしておりソースコードからビルドする必要がある
wget https://cmake.org/files/v3.18/cmake-3.18.4.tar.gz -O - | tar xzvf - \
&& cd cmake-3.18.4/ \
&& wget https://launchpad.net/ubuntu/+source/openssl/1.1.1-1ubuntu2.1~18.04.14/+build/22454676/+files/libssl-dev_1.1.1-1ubuntu2.1~18.04.14_arm64.deb \
&& dpkg -i libssl-dev_1.1.1-1ubuntu2.1~18.04.14_arm64.deb \
&& ./bootstrap && make -j4 install && hash -r