1. はじめに
Arduino Uno QにはLinuxが動作するプロセッサーとArduinoのスケッチでプログラムするマイコンの2つが搭載されています。
Arduino App Labを使用して開発する場合、プロセッサー側のプログラムはPythonで記述し、Arduino Uno Q独自の機能はBrick(s)と呼ばれるライブラリを経由して利用します。
このBricks、サンプルプログラムでは引数が省略されている場合があり、それぞれのBrickが提供しているカスタマイズ性が分かりづらくなっています。
そこで今回はサンプルのDetect Objects on Cameraを題材にしてBrickの使い方を確認しながら、実際に挙動が変わることを確認します。
使用する機器
今回紹介している手順を実行するためには以下の機器が必要です。
()内は記事作成にあたり使用した機器ですが、他の同等な機器でも問題ありません。
- 2. USBカメラ(logicool C270)
- 3. Type-C USBハブ(Elecom DST-W09)* USBカメラを接続するためのType-A端子があること
* PD給電(27W以上)を受け付けること - 4. PD対応 USB Type-C ACアダプタ (Elecom ACDC-PD8445BK)* 45W以上を推奨します
2. そのまま実行してみる
まずは用意されている Detect Objects on Cameraをそのまま実行してみましょう。
このサンプルはUSBカメラを接続する必要があるため、Arduino Uno QをSBCモード(図1の構成)で動作させてください。
図1: Arduino Uno Q SBCモード構成(Detect Objects on Cameraより)
Arduino Uno Qにディスプレイを接続している場合は、Arduino Uno Qのブラウザが立ち上がって画面を確認できます。
接続してない場合は同じネットワークに接続しているPCのブラウザから確認できます。以下のURLにアクセスしてください。
http://unoq.local:8000
このような画面が表示されるはずです。
図2: サンプルアプリケーションの初期表示(Detect Objects on Cameraより)
一目でフレームレートが低いことが分かります。
Arduino App Labから実行している場合、開いたファイルが表示されるエリアの下に"Python"と書かれたボタンがあります。
このボタンを押すと、ログを確認することができます。
図3: Arduino App Labのログ
設定されているフレームレートはこれから確認していきます。また最後に測定用のコードを追加して実際のフレームレートを確認します。
3. Brickの仕様を確認する
VideoObjectDetection Brickのドキュメントを調べる
それではBrickの仕様を確認していきましょう。
まずは以下のコードで呼び出している VideoObjectDetection から調べていきます。
ui = WebUI()
detection_stream = VideoObjectDetection(confidence=0.5, debounce_sec=0.0)
BrickのAPIはArduino App Labで調べることができます。Arduino Uno Qを認識させた後で以下の手順で確認できます。
- 1. 左のペインからBricks Manager以下の Bricksを選択
- 2. 目的のBrick、今回は VideoObjectDetectionを選択
- 3. 上部の選択肢から API Documentationを選択
図4: VideoObjectDetection BrickのAPI Documentation
このドキュメントによると、VideoObjectDetection は以下の引数を受け付けるようになっています。
- camera (
BaseCameraクラス) - confidence (float型)
- debounce_sec (float型)
- camera_preview (bool型)
サンプルでは、 confidenceとdebounce_secのみ指定されていましたが、あと2つ指定できる引数があります。
camera 引数は何も指定されない場合、「デフォルトカメラが初期化されます」(API Documentationの記述を翻訳)。具体的にどのようなカメラ設定になるのか、ソースコードで確認します。
camera 引数を指定しない場合の設定値
camera 引数を指定しない場合、デフォルト値として None が渡されます。
ソースコードを見るとこの場合は Camera クラスが引数なしで呼ばれています。
self._camera = camera if camera else Camera()
Camera クラスについての情報は公式なドキュメントとしては提供されていないようです。
ソースコードを読んでいきましょう。公式レポジトリは arduino/app-bricks-pyです。
このレポジトリの app-bricks-py/src/arduino/app_peripherals/camera/camera.py に Camera クラスの実装があります。
同じディレクトリにある README.md を確認すると、Camera クラスは引数によって以下のカメラクラスを使い分けるようになっています。
CSI CamerasV4L CamerasIP CamerasWebSocket Cameras
Cameraクラスのコンストラクタを見ていきます。引数とそれぞれのデフォルト値は以下の通りです。
表1: Camera クラスのコンストラクタ引数
| 引数 | デフォルト値 | 概要 |
|---|---|---|
source | None | カメラソースを指定する。None の場合は自動でカメラを検出する |
resolution | (640, 480) | フレーム解像度を指定する |
fps | 10 | フレームレートを指定する |
adjustments | None | フレーム調整関数を指定する |
**kwargs | - | カメラ固有のパラメータを指定する |
fpsのデフォルト値 10 が、アプリケーションのFPSに影響している可能性があります。
また、sourceをNoneにした場合はUSBカメラ、CSIカメラの順に使用可能なカメラを調べ、
最初に見つかったカメラを使用するようです。
カメラの画像が見えていることから、sourceは変更する必要はなさそうです。
4. カメラの設定を最適化する
ここからカメラの仕様を確認しつつ、Camera クラスの引数を調整していきます。
まずはカメラが対応している解像度やフレームレートを調べます。
Arduino App Lab 左下の「>_」(Connect to the board's shell)ボタンを押します。
開いたシェルを使い、以下の手順で調べていきます。
-
1.
v4l2-ctl --list-devicesを実行し、V4L2に認識されたカメラのデバイスファイル(/dev/video*形式のファイル)一覧を取得する -
2.1で取得したデバイスファイルに対して
v4l2-ctl -d <デバイスファイル> --list-formatsを実行し、カメラが対応している解像度やフレームレートを確認する。 "Type: Video Capture"という表示の下に対応しているフォーマットが表示されているファイルがUSBカメラに対応するファイルになります -
3.
v4l2-ctl -d <2で特定したデバイスファイル> --list-formats-extを実行し、カメラが提供しているフォーマット、解像度、フレームレートの情報を確認する
私の環境では以下のようになりました。USBカメラのデバイスファイルは/dev/video2で、デフォルトのフォーマットはYUYV、FPSは30でした。
(出力例)
arduino@unoq:~$ v4l2-ctl --list-devices
Qualcomm Venus video decoder (plat:5a00000.video-codec:dec):
/dev/video1
Qualcomm Venus video encoder (plat:5a00000.video-codec:enc):
/dev/video0
UVC Camera (046d:0825) (usb-xhci-hcd.2.auto-1.3):
/dev/video2
/dev/video3
/dev/media0
arduino@unoq:~$ v4l2-ctl -d /dev/video2 --list-formats
ioctl: VIDIOC_ENUM_FMT
Type: Video Capture
[0]: 'YUYV' (YUYV 4:2:2)
[1]: 'MJPG' (Motion-JPEG, compressed)
# --list-formats-extは長いので省略それではFPSを30に変更してみます。Camera クラスを使用するので、インポートも追加します。
+from arduino.app_peripherals.camera import Camera
ui = WebUI()
+camera = Camera(fps=30)
-detection_stream = VideoObjectDetection(confidence=0.5, debounce_sec=0.0)
+detection_stream = VideoObjectDetection(camera, confidence=0.5, debounce_sec=0.0)この状態で再度実行すると、FPSが明らかに向上していることが分かります。
5. 性能比較
数値で性能の変化を比較してみます。
今回は変更する行数を抑えるため、フレーム更新時に呼び出されるcamera.capture に時刻を出力する処理を差し込みました。
from arduino.app_peripherals.camera import Camera
+import time
ui = WebUI()
camera = Camera(fps=30)
+capture = camera.capture
+camera.capture = lambda : print(time.monotonic()) or capture()
detection_stream = VideoObjectDetection(camera, confidence=0.5, debounce_sec=0.0)実行すると、フレームが更新されるたびにコンソールにログが出力されます。
fps 未指定の場合と fps=30 に指定した場合のログを解析した結果が以下になります。
表2: FPS設定による性能比較
| 描画間隔[秒] | FPS | |
|---|---|---|
fps未指定 | 0.20 | 5 |
fps=30 | 0.07 | 15 |
実際にFPSが5から15へ3倍に向上していることが分かります。
ただし、測定したFPSが設定したFPSのおおよそ半分程度になっています。
これはフレームの取得以外の処理(物体検出処理へのデータ送信など)に時間がかかり、カメラがキャプチャしているフレームを一部取りこぼしているためと思われます。
本記事ではこの原因の特定までは踏み込まないことにします。
6. まとめ
Arduino Uno Qで使用できるBrickのドキュメントやソースコードを確認しました。
サンプルでは引数なしで使用されているBrickについて、引数を追加することで設定を変更できることが分かりました。
Arduino Uno Qの性能を確認する際は、実行する環境に合わせてサンプルを調整してから動かしてみてください。
7. 参考資料
8. ネクスティエレクトロニクスの取り組み
株式会社ネクスティ エレクトロニクスは、豊田通商グループのエレクトロニクス事業の中核企業として、カーエレクトロニクスの分野においてトップクラスの規模を誇ります。
技術と商材を核として、幅広い分野でお客さまや世の中のニーズに応え、社会課題のソリューションを提供し、より善き社会の実現に貢献していきます。
また、ネクスティ エレクトロニクスの開発部隊では、取り扱い商材を活用した自社開発、受託開発(ハードウェア、ソフトウェア開発)なども実施しています。
お客さまの困りごとなどの解決なども含め寄り添って対応いたしますので、お気軽にお問合せください。







