Skip to content

Instantly share code, notes, and snippets.

@tonosaman
Created October 6, 2023 09:10
Show Gist options
  • Save tonosaman/1ade4439b3cea189001f44ba857d1842 to your computer and use it in GitHub Desktop.
Save tonosaman/1ade4439b3cea189001f44ba857d1842 to your computer and use it in GitHub Desktop.

AI人物検出を用いた自動入退出記録の設計と実装

AI-Inference, IoT

方針

  • Nvidia DLI(Deep Learning Institute) Dockerイメージを使用
    • libargus でCSIカメラをコンテナ内から操作
    • OpenCV with CUDA + cudaMallocManaged による zero-copy
  • Jupyter notebook 上でOpenCV(Python bind)を呼び出して機能検証
  • サンプルを流用し運用向けにセットアップ

開発機材

Jetson Nano 開発者キット

  • 2GB版 NVIDIA-JETSON-NANO-2GB

    • B01の廉価版, 6~8千円

    • EOL(製造終了)

      Product Lifecycle

      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互換

MIPI CSI-2 カメラ

  • 安価な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付きのものを購入

micro SD カード

64GB以上推奨

  1. JetPack 4.6.1 for Jetson Nano 2GB (L4T 32.7.1)

  2. 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

gstream(3)を用いて動作確認


Dockerイメージ選定

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}

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}

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
  • Dockerfile

  • Running the Docker Container

    #!/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/run.sh

    初回セットアップ時に以下のデータ取得処理が走るので注意

    • Dockerイメージdustynv/jetson-inference:r32.7.1
    • 学習済み分類器・モデル
  • Mounted Data Volumes

    • 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プロトコルのバイパス
  • DockerホストのXディスプレイサーバーへUNIXドメインソケットを経由してウィンドウ表示
  • gdm3(8)のautologinにより、一般ユーザーでXサーバーDISPLAY=:0を確保している
  • コンテナ内PIDがrootにマッピングされてしまう(podman(1)なら...)
  • xhost(1)でコンテナからのXプロトコルを受け付けるように認証を通す必要がある
CSIカメラデバイスI/Oのバイパス
  • --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

jpg ファイルをアーカイブ(<yyyymmdd>.tar)

  • 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代わりにモバイルバッテリを使用して解消

Extra Stage: 追加学習


調査,ネタ

下記無料コースを受講(NVIDIAアカウント登録)して習得

姿勢推定 trt_pose

python3 -m pip install --upgrade pip
python3 -m pip install tqdm pycocotools

ocnnをJetson Nano用にビルド

  • 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

その他

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment