[Raspberry Pi Zero 2W] libcamera-appsでtensorflow liteのpostprocess処理を動かした [メモ]

syurecat.hatenablog.com

の続き。libcamera-appsは撮った画像に対してtensorflow-liteやopencvで後処理を加えることができるようだ。 やりかたはRaspi公式にある。tensoflow-liteで素振りをやってみよう。

ハードはRaspberry Pi Zero 2W ( OSはBullseye ) + imx219

大まかな流れ、tensorflow-liteをインストールしてlibcamera/libcamera-appsをインストール

1. tensorflow liteをビルドインストールする

下記の該当OS(bullseye)のビルドインストール手順 Install TensorFlow 2 Lite on Raspberry Pi 4 - Q-engineering

2. libcamera/libcamera-appsをビルド・インストールする

ソースからビルド/インストールする前にaptコマンドで入れたlibcamera/libcamera-appとかは削除しておきましょう。相当ハマった。

DENABLE_TFLITE等使いたいものは有効にする libcameraは普通に入れても良かったけどlibcamera-appsとの関係がうまくいってないことがあったのでソースから入れた。うまく動かなかったらIssueを見る。

Raspberry Pi Documentation - Camera

3. いろいろ遊ぶ

Raspberry Pi Documentation - Camera

libcamera-hello --post-process-file object_detect_tf.json --lores-width 400 --lores-height 300

@raspberrypi:~/postprocess-tf $ libcamera-jpeg --post-process-file object_detect_tf.json --lores-width 400 --lores-height 300 -o test.jpg
Preview window unavailable
[26:12:07.198492412] [5299]  INFO Camera camera_manager.cpp:293 libcamera v0.0.0+3777-69ae75b0
[26:12:07.238774844] [5300]  WARN RPI raspberrypi.cpp:1252 Mismatch between Unicam and CamHelper for embedded data usage!
[26:12:07.240241518] [5300]  INFO RPI raspberrypi.cpp:1368 Registered camera /base/soc/i2c0mux/i2c@1/imx219@10 to Unicam device /dev/media3 and ISP device /dev/media0
Reading post processing stage "object_detect_tf"
TfStage: Loaded model /home/heyanaohiro/postprocess-tf/detect.tflite
INFO: Created TensorFlow Lite XNNPACK delegate for CPU.
Read 90 labels
Reading post processing stage "object_detect_draw_cv"
[26:12:07.414347455] [5299]  INFO Camera camera.cpp:1029 configuring streams: (0) 1640x1232-YUV420 (1) 400x300-YUV420
[26:12:07.415355794] [5300]  INFO RPI raspberrypi.cpp:759 Sensor: /base/soc/i2c0mux/i2c@1/imx219@10 - Selected sensor format: 1640x1232-SBGGR10_1X10 - Selected unicam format: 1640x1232-pBAA
TfStage: Low resolution stream is 400x300
TfStage: Main stream is 1640x1232
cell phone[76] (0.5) @ 209,20 1230x1219
TfStage: Inference time: 411081 ms
TfStage: Inference time: 276767 ms
TfStage: Inference time: 276667 ms
cell phone[76

写したのはパソコン用モニター、 まあcellphoneに見えるといえば見えるからヨシッ

苦労ポイント: tensorflow-liteのインストール方法がよくわかんなくていろいろ探した。 ビルドに時間かかったのでクロスコンパイル?ができたらいいんだけどね、調べるより寝る合間にビルド走らせてればOKという解決になってしまった。

Raspberry Pi Zero 2 Wでカメラ libcamera-still

https://syurecat.hatenablog.com/entry/2022/06/25/201610

👆ではOSをレガシーに変更してraspstillを利用したけど、bullseyeからは raspstill から libcameraに移行したらしい

www.raspberrypi.com

@raspberrypi:~ $ lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description:    Raspbian GNU/Linux 11 (bullseye)
Release:    11
Codename:   bullseye

メモリがなくて怒られる↓

heyanaohiro@raspberrypi:~ $ libcamera-still -r -o test.jpg
Preview window unavailable
[0:01:35.304669580] [704]  INFO Camera camera_manager.cpp:293 libcamera v0.0.0+3544-22656360
[0:01:35.413496356] [705]  WARN RPI raspberrypi.cpp:1241 Mismatch between Unicam and CamHelper for embedded data usage!
[0:01:35.414759737] [705]  INFO RPI raspberrypi.cpp:1356 Registered camera /base/soc/i2c0mux/i2c@1/imx219@10 to Unicam device /dev/media3 and ISP device /dev/media0
[0:01:35.415967806] [704]  INFO Camera camera.cpp:1029 configuring streams: (0) 1640x1232-YUV420
[0:01:35.417044417] [705]  INFO RPI raspberrypi.cpp:760 Sensor: /base/soc/i2c0mux/i2c@1/imx219@10 - Selected sensor format: 1640x1232-SBGGR10_1X10 - Selected unicam format: 1640x1232-pBAA
[0:01:40.550753473] [704]  INFO Camera camera.cpp:1029 configuring streams: (0) 3280x2464-YUV420 (1) 3280x2464-SBGGR10_CSI2P
[0:01:40.556287991] [705]  INFO RPI raspberrypi.cpp:760 Sensor: /base/soc/i2c0mux/i2c@1/imx219@10 - Selected sensor format: 3280x2464-SBGGR10_1X10 - Selected unicam format: 3280x2464-pBAA
[0:01:40.660953470] [705] ERROR V4L2 v4l2_videodevice.cpp:1211 /dev/video14[14:cap]: Unable to request 1 buffers: Cannot allocate memory
[0:01:40.661161439] [705] ERROR RPI raspberrypi.cpp:1008 Failed to allocate buffers
ERROR: *** failed to start camera ***

/boot/config.txtにdtoverlay=cma,cma-128を追加

heyanaohiro@raspberrypi:~ $ libcamera-still -o test.jpg
Preview window unavailable
[0:00:37.601972848] [699]  INFO Camera camera_manager.cpp:293 libcamera v0.0.0+3544-22656360
[0:00:37.760509671] [700]  WARN RPI raspberrypi.cpp:1241 Mismatch between Unicam and CamHelper for embedded data usage!
[0:00:37.761834151] [700]  INFO RPI raspberrypi.cpp:1356 Registered camera /base/soc/i2c0mux/i2c@1/imx219@10 to Unicam device /dev/media3 and ISP device /dev/media1
[0:00:37.763132588] [699]  INFO Camera camera.cpp:1029 configuring streams: (0) 1640x1232-YUV420
[0:00:37.763977015] [700]  INFO RPI raspberrypi.cpp:760 Sensor: /base/soc/i2c0mux/i2c@1/imx219@10 - Selected sensor format: 1640x1232-SBGGR10_1X10 - Selected unicam format: 1640x1232-pBAA
[0:00:42.900641649] [699]  INFO Camera camera.cpp:1029 configuring streams: (0) 3280x2464-YUV420 (1) 3280x2464-SBGGR10_CSI2P
[0:00:42.902535451] [700]  INFO RPI raspberrypi.cpp:760 Sensor: /base/soc/i2c0mux/i2c@1/imx219@10 - Selected sensor format: 3280x2464-SBGGR10_1X10 - Selected unicam format: 3280x2464-pBAA
Still capture image received

撮れてる

CMAとは gihyo.jp

UDPでストリーミングもできるらしい。

raspberrypi:~ $ libcamera-vid -t 0 --inline -o udp://[クライアントのIPaddr]:9999

クライアントでvlc

$vlc udp://@:9999 :demux=h264

画質はイマイチ。設定を試行錯誤していく必要がありそう?

ドキュメントを読むと色々できるっぽい↓ www.raspberrypi.com

v4l2/ffmepg?にもトライしてみたけどうまく行かなかったので要勉強 (プログラムから呼び出したい)

[video4linux2,v4l2 @ 0x1a20d20] ioctl(VIDIOC_G_PARM): Inappropriate ioctl for device
[video4linux2,v4l2 @ 0x1a20d20] Time per frame unknown
[video4linux2,v4l2 @ 0x1a20d20] ioctl(VIDIOC_STREAMON): Invalid argument
/dev/video0: Invalid argument

と思ったけど、libcameraはv4l2の発展系?みたいなのでOpenっぽいし、これはこれでいいか(?)

libcamera.org

k3sのagentをRaspberry Pi Zero 2 Wで動かした

k3sはk8sの軽量版。サーバとエージェントに分かれてエッジの用途にもフォーカスされているらしい。 k3sの説明はこちら Rancher labs社のPDF https://rancher.co.jp/pdfs/K3s-eBook4Styles0507.pdf

使ったOSはRaspberry Pi OS (32bit) Debian Bullseye。 インストールは下記を参考に行った。 future-architect.github.io 但し、Raspberry Pi OS (32bit) Debian Bullseyeはcgroupがデフォルトで有効になっておらず。 agentの起動時に下記のようにログにエラーが出るので/boot/cmdline.txtにcgroup_memory=1 cgroup_enable=memoryを追加して再起動

$ journalctl -u k3s-agent
 6月 26 01:47:27 raspberrypi k3s[977]: time="2022-06-26T01:47:27+01:00" level=info msg="Starting k3s agent v1.23.6+k...
 6月 26 01:47:27 raspberrypi k3s[977]: time="2022-06-26T01:47:27+01:00" level=fatal msg="failed to find memory cgroup...
 6月 26 01:47:27 raspberrypi systemd[1]: k3s-agent.service: Main process exited, code=exited, status=1/FAILURE
 6月 26 01:47:27 raspberrypi systemd[1]: k3s-agent.service: Failed with result 'exit-code'.
cat  /boot/cmdline.txt
console=serial0 ... plymouth.ignore-serial-consoles cgroup_memory=1 cgroup_enable=memory

サーバ側から確認する

(base) ~/k3s-raspi$ k3s kubectl get nodes
NAME          STATUS   ROLES    AGE     VERSION
raspberrypi   Ready    <none>   5m37s   v1.23.6+k3s1

大丈夫そう。 試しにkellygriffin/hello:v1を動かす。

(base):~/k3s-raspi$ kubectl get pods
NAME                      READY   STATUS             RESTARTS      AGE
mysite-57b5b46f97-ftvcq   0/1     CrashLoopBackOff   3 (15s ago)   95s
(base):~/k3s-raspi$ kubectl logs mysite-57b5b46f97-ftvcq
standard_init_linux.go:228: exec user process caused: exec format error
(base):~/k3s-raspi$ kubectl get pods --

だめっぽい。とりあえず、deploymentは消しとく。

(base) :~/k3s-raspi$ kubectl delete deployment mysite

エラーメッセージから察するにkellygriffin/helloはarmv7lでは動かないっぽい(?) ので動きそうな名前をしているarm32v7/hello-world:latestをJobで実行することでお茶を濁す

apiVersion: batch/v1
kind: Job
metadata:
  name: workload
spec:
  template:
    metadata:
      labels:
        app: workload
    spec:
      containers:
        - name: workload
          image: arm32v7/hello-world:latest
      restartPolicy: Never
  backoffLimit: 4

(base) ~/k3s-raspi$ kubectl apply -f ./testdeploy.yaml 
job.batch/workload created
(base) ~/k3s-raspi$ kubectl get pods
NAME             READY   STATUS              RESTARTS   AGE
workload-lt7hz   0/1     ContainerCreating   0          3s
(base) ~/k3s-raspi$ kubectl logs workload-lt7hz -f

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (arm32v7)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

(base)~/k3s-raspi$ kubectl get pods
NAME             READY   STATUS      RESTARTS   AGE
workload-lt7hz   0/1     Completed   0          30s

めでたしめでたし

Raspberry Pi Zero 2 WとカメラをGET

Raspberry Pi Zero 2 Wを手に入れたので遊ぶためにセットアップ www.switch-science.com

OSインストールしてカメラとかいろいろつないで(下にAmazonで買ったやつ貼っといた) カメラはPibiger 8M Pixel Camera IMX219とかいう怪しいのかなんなのかわからない安いやつ

起動→写真が撮りたいと思い RaspiOSに入っているらしい写真を撮れるコマンドを叩くもError

@raspberrypi:~ $ raspistill -w 480 -h 360 -n -o test.jpg
ERROR: the system should be configured for the legacy camera stack

なにやらOSのバージョン云々でraspistillコマンドがレガシーモードじゃないと動かないらしいので OSの設定を探す。 (注記:libcameraが代替らしくそっちはbullseyeでもちゃんと動く  syurecat.hatenablog.com

 sudo raspi-config

InterfaceOption > LegacyCamera Support を Enable

raspistill -w 480 -h 360 -n -o test.jpg

写真が撮れた。

ピントが全然合ってないが、写ってるのでOK raspistillはがっつり使う予定ではないのでOSの設定を戻しておく。 ちなみに、ケースにカメラ用穴があるけどどう考えてもこのカメラは収まらないので改造するしか無さそう