Raspberry Pi とAI HAT+を使って、yoloの物体認識を試す

ラズパイに外付けのアクセラレータ（NPU)を使うと、AIの推論速度が速くなるらしい。
デフォルトのyoloのsmallモデルで640ピクセルだと、十分リアルタイムでした。

人間が手を動かして動作確認した記録です。

（公式を自動翻訳）
AI HAT+は、Raspberry Pi 5のPCIeインターフェースを使って通信します。ホスト側のRaspberry Pi 5は、搭載されているHailoアクセラレータを自動的に認識し、対応するAIコンピューティングタスクにNPU（ニューラルプロセッシングユニット）を使用します。Raspberry Pi OSに標準で搭載されている`rpicam-apps`カメラアプリケーションは、対応するポストプロセッシングタスクを実行する際に自動的にNPUを活用します。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1520250/5464d23b-20dc-4e38-8c31-4aa9e6cf58ea.png)

https://www.raspberrypi.com/documentation/accessories/ai-hat-plus.html

似た製品で、接続がm2のものがあるので、公式マニュアルを読むとき混同に注意
https://hailo.ai/ja/products/ai-accelerators/hailo-8-m2-ai-acceleration-module/#hailo8-m2-features

## 準備
HATの物理的な取り付け（PCIeのリボンケーブル、固定金具)
ラズパイカメラの取り付け（リボンケーブル）
マイクロSDカード（最新2025.6.2のbookworm 64bit）をラズパイメージャで作成。

### ターミナルでインストール作業
上記HPを参考に、
```bash
sudo apt update && sudo apt full-upgrade -y
sudo rpi-eeprom-update
#ファームウェア確認。2023.12より古い場合はHP情報を見て更新
sudo raspi-config
```

以下のページを参考に、PCIeをGen3モードに変える。
https://github.com/hailo-ai/hailo-rpi5-examples/blob/main/doc/install-raspberry-pi5.md#how-to-set-up-raspberry-pi-5-and-hailo
```bash
sudo raspi-config
```
Select option "6 Advanced Options", then select option "A8 PCIe Speed". Choose "Yes" to enable PCIe Gen 3 mode. Click "Finish" to exit.
再起動をすること

### hailortcli などのツール群のインストール
以下のページをクローンして作業を進める。
https://github.com/hailo-ai/hailo-rpi5-examples

```bash
git clone https://github.com/hailo-ai/hailo-rpi5-examples.git
cd hailo-rpi5-examples
./install.sh
```
これで、専用のvenv環境が用意される。

以下のコマンドで、hailortcliが入る。
```bash
sudo apt install hailo-all -y
```
必要に応じ再起動。

このページ（再掲）の後半の確認作業が可能になる。
https://github.com/hailo-ai/hailo-rpi5-examples/blob/main/doc/install-raspberry-pi5.md#how-to-set-up-raspberry-pi-5-and-hailo
```bash
hailortcli fw-control identify
gst-inspect-1.0 hailotools
gst-inspect-1.0 hailo
```
出力抜粋 ボード名とアーキテクチャが表示される。
Board Name: Hailo-8
Device Architecture: HAILO8

### venv環境の起動

普段通りに、source ./bin/activate で起動しないこと。環境変数の設定が組み込まれている公式の起動法を使う。
```bash
source setup_env.sh
(venv_hailo_rpi5_examples) pi@pi:~/hailo-rpi5-examples $ 
# 括弧付きでvenv環境名が表示されていることを確認。
```
このvenv環境中でサンプル動画のデモを実行
```
python basic_pipelines/detection_simple.py
```
録画済み動画で認識デモが行われる。
なぜか、うまく行かない場合があった。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1520250/26c81dd1-0609-43ae-8d9b-393366d3d198.png)
### カメラでの認識
念のため、カメラ認識のテストをする。ラズパイカメラならドライバやconfigをさわらずに、うごくはず。
```bash
rpicam-hello
```
画像が数秒間表示されればＯＫ
ラズパイでのカメラ制御が、大きく変わっているのでレガシーな４種類のコマンド(raspistill, raspivid、raspiyuv 、 raspividyuv)の人は、知識をアップデート。

先ほどと同じvenv環境で
```bash
python basic_pipelines/detection.py --input rpi
```
デフォルトのyolo認識モデルが動作すればＯＫ

以下のような表示のまま、止まってしまう場合があった。何度か繰り返すと起動したりする。カメラ周りのデバイスがコンフリクトしているようだが、はっきりしない。
```
[0:08:11.583665780] [2012]  INFO RPI pisp.cpp:1483 Sensor: /base/axi/pcie@1000120000/rp1/i2c@88000/imx219@10 - Selected sensor format: 1920x1080-SBGGR10_1X10 - Selected CFE format: 1920x1080-PC1B
Picamera2 configuration: width=1280, height=720, format=RGB
picamera_process started
```
### ＵＳＢカメラを使う時、起動オプション

入力をＵＳＢカメラにするときは --input usb を付ける。大文字でも小文字でもＯＫ。
古いカメラで使えないものもあった。

```
get-usb-camera
       # カメラのデバイスを見つけて直接指定しても良い。　USB cameras found on: /dev/video8

python basic_pipelines/detection.py --input /dev/video8
```

https://github.com/hailo-ai/hailo-rpi5-examples/blob/main/README.md

オプションはヘルプコマンドで見ることができる。

```
python basic_pipelines/detection.py --help
usage: detection.py [-h] [--input INPUT] [--use-frame] [--show-fps] [--arch {hailo8,hailo8l}] [--hef-path HEF_PATH]
                    [--disable-sync] [--disable-callback] [--dump-dot] [--labels-json LABELS_JSON]

Hailo App Help

options:
  -h, --help            show this help message and exit
  --input INPUT, -i INPUT
                        Input source. Can be a file, USB (webcam), RPi camera (CSI camera module) or ximage. For RPi
                        camera use '-i rpi' For automatically detect a connected usb camera, use '-i usb' For
                        manually specifying a connected usb camera, use '-i /dev/video<X>' Defaults to application
                        specific video.
  --use-frame, -u       Use frame from the callback function
  --show-fps, -f        Print FPS on sink
  --arch {hailo8,hailo8l}
                        Specify the Hailo architecture (hailo8 or hailo8l). Default is None , app will run check.
  --hef-path HEF_PATH   Path to HEF file
  --disable-sync        Disables display sink sync, will run as fast as possible. Relevant when using file source.
  --disable-callback    Disables the user's custom callback function in the pipeline. Use this option to run the
                        pipeline without invoking the callback logic.
  --dump-dot            Dump the pipeline graph to a dot file pipeline.dot
  --labels-json LABELS_JSON
                        Path to costume labels JSON file

```

### モデルなどのリソースをダウンロード
githubのリポジトリからdocフォルダを見ている。
https://github.com/hailo-ai/hailo-rpi5-examples/blob/main/doc/basic-pipelines.md

```
./download_resources.sh --all
```
pip install -r requirements.txtのスクリプトもマニュアルにあるが、これまでの作業で既にインストール済みのようだ。
デバッカーは必要に応じ追加する。
pip install ipdb

### バーコード検出デモ
サンプルコマンドそのまま。yolo8sにバーコードを学習させて、hef形式（AI HAT+専用形式）に変換したモデルを使うようだ。
--labels-jsonオプションを省略すると、デフォルトのラベル（この場合 person）が表示される。
```
python basic_pipelines/detection.py --labels-json resources/barcode-labels.json --hef-path resources/yolov8s-hailo8l-barcode.hef --input resources/barcode.mp4
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1520250/47e84719-db3e-491c-b28b-943082265262.png)


### オリジナルのモデルを作る（別のマシンで作業）
ここにバーコード認識モデルを作成したときに手法が記述されている。
ubuntuの母艦でdockerコンテナで実行しているようだ。yoloの学習部分は、dockerは使わなくても大丈夫と思われる。
https://github.com/hailo-ai/hailo-rpi5-examples/blob/main/doc/retraining-example.md

先ずは、通常のyoloの手法でモデルを学習
yolo11での学習例はこちら

https://qiita.com/katakaku/items/d24118bfcb194b537198

yolo detect train data=/data/barcode-detect/data.yaml model=yolov8s.pt name=retrain_yolov8s epochs=20 batch=8

次は、ONNX形式で出力
yolo export model=/workspace/ultralytics/runs/detect/retrain_yolov8s/weights/best.pt imgsz=640 format=onnx opset=11

最後に、AI HAT+のオリジナル形式に変換する。
ツールの準備（Developer Zoneに登録して、Hailo AI SW-Suite をＤＬしてインストール）

https://hailo.ai/developer-zone/software-downloads/

hailomz compile yolov8s --ckpt=barcode-detection.onnx --hw-arch hailo8l --calib-path barcode-detect/test/images/ --classes 2 --performance

**yolo11のモデルでも変換できるのか？small以外にmidやlargeでも動作するか？画像サイズが640より大きくても利用できるのか？** について検討したい。
－＞yolo11m入力640はOK.


# ツール（Hailo AI SW-Suite）を試してみる
## 開発用ツールの準備(ubuntuマシン上で作業）
まずは、サイトに登録して「Hailo AI Software Suite – Docker」ダウンロードをしてみる。
開発環境は、ubuntuのコンテナしか無いのかな？windowsの人はWSLかな？
通常版のdockerを使っていると、コンテナ内でGPUが使えない(nvidia-smiが使えない）ので、nvidia-docker2 を使ってない人はインストール作業が必要。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1520250/54fb5809-79ad-4ec2-acba-ff87a1e41bb7.png)
ダウンロードして、解凍すると、hailo_ai_sw_suite_docker_run.sh ファイルと圧縮されたコンテナが作成されるので以下のコマンドを実行
先ずは、ヘルプコマンドで何ができるか調べる。
```
$ ./hailo_ai_sw_suite_docker_run.sh --help
Running Hailo AI Software Suite Docker image:
The default mode will create a new container. If one already exists, use --resume / --override

  -h, --help                                 Show help
  --resume                                   Resume the old container
  --override                                 Delete the existing container and start a new one
  --hailort-enable-service                   Run HailoRT service

  Options for HailoRT service:
  --service-enable-monitor
  --service-hailort-logger-path </path>      Note: the path is set inside docker container

```

## Docker開発環境の起動
./hailo_ai_sw_suite_docker_run.shを実行する。
```
./hailo_ai_sw_suite_docker_run.sh

Loaded image: hailo_ai_sw_suite_2025-04:1
Starting new container
Running Hailo AI SW suite Docker image with the folowing Docker command:
docker run --privileged --net=host -e DISPLAY=:20 -e XDG_RUNTIME_DIR=/run/user/1000 --device=/dev/dri:/dev/dri --ipc=host --group-add 44 -v /dev:/dev -v /lib/firmware:/lib/firmware -v /lib/modules:/lib/modules -v /lib/udev/rules.d:/lib/udev/rules.d -v /usr/src:/usr/src -v /tmp/hailo_docker.xauth:/home/hailo/.Xauthority -v /tmp/.X11-unix/:/tmp/.X11-unix/ --name hailo_ai_sw_suite_2025-04_container -v /var/run/docker.sock:/var/run/docker.sock -v /etc/machine-id:/etc/machine-id:ro -v /var/run/dbus/system_bus_socket:/var/run/dbus/system_bus_socket -v /home/ichi/hailo_ai_sw_suite/shared_with_docker/:/local/shared_with_docker:rw -v /etc/timezone:/etc/timezone:ro -v /etc/localtime:/etc/localtime:ro -v /var/lib/dkms:/var/lib/dkms --gpus all -ti hailo_ai_sw_suite_2025-04:1

==========
== CUDA ==
==========

CUDA Version 11.8.0

Container image Copyright (c) 2016-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.

This container image and its contents are governed by the NVIDIA Deep Learning Container License.
By pulling and using the container, you accept the terms and conditions of this license:
https://developer.nvidia.com/ngc/nvidia-deep-learning-container-license

A copy of this license is made available in this container at /NGC-DL-CONTAINER-LICENSE for your convenience.



Welcome to Hailo AI Software Suite Container
To list available commands, please type:

----------------------------------------------------

HailoRT:                hailortcli -h
Dataflow Compiler:      hailo -h
Hailo Model Zoo:        hailomz -h
TAPPAS:                 hailo_run_app -h

----------------------------------------------------

```
しばらく待つと、コンテナ内のターミナルが表示される。

## VS-codeにコンテナをアタッチする
先ほどのターミナルで作業しても良いが、VS-codeの方が見やすい。
コンテナ拡張機能を追加したVScodeを開く。左側の拡張機能（コンテナ）のアイコンを押して、稼働中のコンテナからhailo_ai_sw_suiteを右クリックするVScodeにアタッチするを選ぶ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1520250/c28d657b-d9dd-400c-a75d-2ef3454f91fc.png)

フォルダを選べるので、/localを選ぶ。
shared_with_dockerフォルダは、コンテナの内側と外側両方から見えるので、データ受け渡しに使う。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1520250/676942ce-b665-4579-a62b-8003ce9249fe.png)

別途作成したonnxファイルを**hailomz compile**コマンドで、hefファイルに変換する。

```
hailomz compile --yaml /local/workspace/hailo_model_zoo/hailo_model_zoo/cfg/networks/yolov11m.yaml --ckpt /local/shared_with_docker/yolo11m640.onnx --hw-arch hailo8 --classes 80  --calib-path /local/shared_with_docker/coco128seg-images/
```
オプション
--yaml 設定ファイル　/local/workspace/hailo_model_zoo/hailo_model_zoo/cfg/networks/から探す。
--ckpt 変換元のonnxファイル。
--hw-arch hailo8 　　AIHAT+のアーキテクチャ(ラズパイ用）
--classes 80  クラス分類の数（今回はcocoデータそのままなので、80）
--calib-path 必須オプションのよう。量子化の精度を維持するため学習に使った画像を与える。

オプションや使用方法は、docker起動時に作成される共有フォルダのマニュアル「hailo_model_zoo_v2.15.0.pdf」に詳しい。

--performanceオプションはお任せで精度向上するらしい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1520250/d00c2fe5-cdd9-434e-8ac2-c4b35d7c7d80.png)

１時間以上かかって、hefファイルが作成された。
ラズパイにコピーして利用可能。


### ＣＬＩＰ
画像言語モデルの中でも基盤モデルと言われるCLIPが使えるようだ。今回は手を出さない。

https://github.com/hailo-ai/hailo-CLIP

### ラズパイのカメラ認識について（動作安定に向けて、今後の検討課題）
lsof /dev/video* をつかって、どのソフトがカメラを制御しているのか見てみる。

まずは、起動直後。pipewireと関連のwireplumbが起動している。
```
pi@piyolo:~ $ lsof /dev/video*
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
pipewire  898  pi   70u   CHR  81,21      0t0  706 /dev/video4
pipewire  898  pi   71u   CHR  81,24      0t0  709 /dev/video7
pipewire  898  pi   72u   CHR  81,23      0t0  708 /dev/video6
pipewire  898  pi   73u   CHR   81,1      0t0  540 /dev/video20
pipewire  898  pi   74u   CHR   81,4      0t0  546 /dev/video23
pipewire  898  pi   75u   CHR   81,5      0t0  547 /dev/video24
pipewire  898  pi   76u   CHR   81,8      0t0  550 /dev/video27
pipewire  898  pi   77u   CHR   81,2      0t0  541 /dev/video21
pipewire  898  pi   78u   CHR   81,6      0t0  548 /dev/video25
pipewire  898  pi   79u   CHR   81,3      0t0  545 /dev/video22
pipewire  898  pi   80u   CHR   81,7      0t0  549 /dev/video26
wireplumb 902  pi   44u   CHR  81,21      0t0  706 /dev/video4
wireplumb 902  pi   45u   CHR  81,24      0t0  709 /dev/video7
wireplumb 902  pi   46u   CHR  81,23      0t0  708 /dev/video6
wireplumb 902  pi   47u   CHR   81,1      0t0  540 /dev/video20
wireplumb 902  pi   48u   CHR   81,4      0t0  546 /dev/video23
wireplumb 902  pi   49u   CHR   81,5      0t0  547 /dev/video24
wireplumb 902  pi   50u   CHR   81,8      0t0  550 /dev/video27
wireplumb 902  pi   51u   CHR   81,2      0t0  541 /dev/video21
wireplumb 902  pi   52u   CHR   81,6      0t0  548 /dev/video25
wireplumb 902  pi   53u   CHR   81,3      0t0  545 /dev/video22
wireplumb 902  pi   54u   CHR   81,7      0t0  549 /dev/video26
```
ＡＩカメラ認識動作中のとき。
先ほどのpipewireと関連のwireplumbに加えて、Hailo\x20が起動している。
制御先のデバイス名は完全に重複している。

```
pi@piyolo:~ $ lsof /dev/video*
COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
pipewire   898  pi   70u   CHR  81,21      0t0  706 /dev/video4
pipewire   898  pi   71u   CHR  81,24      0t0  709 /dev/video7
pipewire   898  pi   72u   CHR  81,23      0t0  708 /dev/video6
pipewire   898  pi   73u   CHR   81,1      0t0  540 /dev/video20
pipewire   898  pi   74u   CHR   81,4      0t0  546 /dev/video23
pipewire   898  pi   75u   CHR   81,5      0t0  547 /dev/video24
pipewire   898  pi   76u   CHR   81,8      0t0  550 /dev/video27
pipewire   898  pi   77u   CHR   81,2      0t0  541 /dev/video21
pipewire   898  pi   78u   CHR   81,6      0t0  548 /dev/video25
pipewire   898  pi   79u   CHR   81,3      0t0  545 /dev/video22
pipewire   898  pi   80u   CHR   81,7      0t0  549 /dev/video26
wireplumb  902  pi   44u   CHR  81,21      0t0  706 /dev/video4
wireplumb  902  pi   45u   CHR  81,24      0t0  709 /dev/video7
wireplumb  902  pi   46u   CHR  81,23      0t0  708 /dev/video6
wireplumb  902  pi   47u   CHR   81,1      0t0  540 /dev/video20
wireplumb  902  pi   48u   CHR   81,4      0t0  546 /dev/video23
wireplumb  902  pi   49u   CHR   81,5      0t0  547 /dev/video24
wireplumb  902  pi   50u   CHR   81,8      0t0  550 /dev/video27
wireplumb  902  pi   51u   CHR   81,2      0t0  541 /dev/video21
wireplumb  902  pi   52u   CHR   81,6      0t0  548 /dev/video25
wireplumb  902  pi   53u   CHR   81,3      0t0  545 /dev/video22
wireplumb  902  pi   54u   CHR   81,7      0t0  549 /dev/video26
Hailo\x20 1971  pi   29u   CHR  81,21      0t0  706 /dev/video4
Hailo\x20 1971  pi   30u   CHR  81,24      0t0  709 /dev/video7
Hailo\x20 1971  pi   31u   CHR  81,23      0t0  708 /dev/video6
Hailo\x20 1971  pi   32u   CHR   81,1      0t0  540 /dev/video20
Hailo\x20 1971  pi   33u   CHR   81,4      0t0  546 /dev/video23
Hailo\x20 1971  pi   34u   CHR   81,5      0t0  547 /dev/video24
Hailo\x20 1971  pi   35u   CHR   81,8      0t0  550 /dev/video27
Hailo\x20 1971  pi   36u   CHR   81,2      0t0  541 /dev/video21
Hailo\x20 1971  pi   37u   CHR   81,6      0t0  548 /dev/video25
Hailo\x20 1971  pi   38u   CHR   81,3      0t0  545 /dev/video22
Hailo\x20 1971  pi   39u   CHR   81,7      0t0  549 /dev/video26
pi@piyolo:~ $ 
```
重複していても問題無いのか？