
前回、カメラの解像度の低さが気になったので、今回はOV2640使用200万画素カメラ フレームバッファ付き M12ピンホール B0067に変えてやってみます。
開発環境はラズパイ4 Model B にビルトインされているC/C++ 。
上記ページではカメラはHM01B0が参照されていますが、実際に使われているの2MPのB0067 です。
データ送信にUSBシリアル変換用コンバーターモジュールも使います。
カメラとPico の結線
USBtoTTL とPico の結線
ラズパイ4ModelB でPico のセットアップ
表示用に使っているアプリProcessing との相性で32-bitを使用。
OSはDebian 12 (Bookworm)Desktop (32-bit)
このセットアップで何が実行されるのかは、PICO Arducam Examplesの Quick Pico Setupに書かれています。
Raspberry Pi 4B または Raspberry Pi 400 で Raspberry Pi Pico 用に開発している場合、インストールの大部分はこの入門ガイドの手順は、セットアップ スクリプトを実行することでスキップできます。
1 |
git clone https://github.com/raspberrypi/pico-setup.git |
セットアップシェルを実行
1 |
pico-setup/pico_setup.sh |
● pico というディレクトリを作成します
● 必要な依存関係をインストールします
● pico-sdk、pico-examples、pico-extras、pico-playground リポジトリをダウンロードします
● ~/.bashrc で PICO_SDK_PATH、PICO_EXAMPLES_PATH、PICO_EXTRAS_PATH、PICO_PLAYGROUND_PATH を定義します
● pico-examples/build/blink と pico-examples/build/hello_world で blink と hello_world の例をビルドします
● picotool をダウンロードしてビルドします 。/usr/local/bin にコピーします。 • picoprobe をダウンロードしてビルドします 。
● OpenOCD をダウンロードしてコンパイルする (デバッグ サポート用)
● Visual Studio Code をダウンロードしてインストールする
● 必要な Visual Studio Code 拡張機能をインストールする (詳細については第 6 章を参照)
● Raspberry Pi UART を Raspberry Pi Pico で使用するように構成する
● 実行したら、Raspberry Pi を再起動
1 |
sudo reboot |
実行環境用ファイル(uf2)をソースからコンパイル
ソースダウンロード
1 |
git clone https://github.com/ArduCAM/RPI-Pico-Cam.git |
TensorFlow Lite Micro を使ったTinyML の人物検出の実行環境を作成します。
主に浮動小数点演算を8bit整数演算に変換することで実行サイズを削減する手法が使われているようです。精度は少々低下しますが、TinyML ではよく使われる方法です。
コンパイル実行
1 2 3 4 5 6 |
cd RPI-Pico-Cam/tflmicro mkdir build cd build cmake .. make |
RPI-Pico-Cam/tflmicro/build/examples/person_detection で以下のファイルを確認
person_detection_int8.uf2
*ソース
RPI-Pico-Cam/tflmicro/examples/person_detection
注:make に失敗した場合
●numeric_limits、max、min関連でerrorが発生していたら……..
~/RPI-Pico-Cam/tflmicro/src/tensorflow/lite/micro/micro_utils.hに以下のインクルードファイルを追加して再度makeを実行してみてください。
#include <limits>
コンパイルが通ったら~/RPI-Pico-Cam/tflmicro/build/examples/person_detectionにperson_detection_int8.uf2が作成されていることを確認
person_detection_int8以外に5つほどuf2ファイルが作成されています。どういう機能を持っているかは調査中。
●ArduCAM/RPI-Pico-Camからコンパイル済みのuf2ファイルをダウンロードする手もあります。
person_detection_int8.uf2のzipファイル
UF2ファイルをPico のフラッシュメモリにコピーして、再起動
BOOTSEL ボタンを押しながらUSBケーブルを接続
Pico はストレージとして認識されます。
上記のperson_detection_int8.uf2をドラッグ・ドロップ。
uf2ファイルがコピーされるとPico は即再起動されます。
Processingで画像と実行結果表示
インストールはPi Pico でエッジAI を試してみる(1)カメラの4/5を参照
更に、processing のフォルダーにあるinstall.sh を実行してメニュに追加。Touch 周りの警告がいっぱいでますが、気にしません。
メニュにProcessing IDE が現れます。ここから起動できます。
シリアルポートを以下のコマンドでUSBtoTTLを抜き差しして、確認します。
ls /dev/tty*
processingの実行スクリプトを以下から取得します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
/* This sketch reads a raw Stream of RGB565 pixels from the Serial port and displays the frame on the window. Use with the Examples -> CameraCaptureRawBytes Arduino sketch. This example code is in the public domain. */ import processing.serial.*; import java.nio.ByteBuffer; import java.nio.ByteOrder; Serial myPort; // must match resolution used in the sketch final int cameraWidth = 96; final int cameraHeight = 96; final int cameraBytesPerPixel = 1; final int bytesPerFrame = cameraWidth * cameraHeight * cameraBytesPerPixel; PImage myImage; byte[] frameBuffer = new byte[bytesPerFrame]; byte[] header = new byte[3]; byte[] score = new byte[2]; void setup() { size(320, 320); // if you have only ONE serial port active //myPort = new Serial(this, Serial.list()[0], 9600); // if you have only ONE serial port active // if you know the serial port name //myPort = new Serial(this, "COM4", 921600); // Windows myPort = new Serial(this, "/dev/ttyUSB0", 921600); // Linux // myPort = new Serial(this, "/dev/cu.usbmodem14401", 921600); // Mac // wait for full frame of bytes myPort.buffer(bytesPerFrame); myImage = createImage(cameraWidth, cameraHeight, GRAY); PFont f; f = createFont("Arial",16,true); // Arial, 16 point, anti-aliasing on textFont(f,20); fill(255, 0, 0); } void draw() { image(myImage, 0, 0, 320, 320); String text = String.format("Person: %.2f%%", ((score[0] + 128)/256.0 * 100)); text(text, 0, 25); } int state = 0; int read = 0; int result = 0; int startbyte; void serialEvent(Serial myPort) { if (read == 0) { startbyte = myPort.read(); if (startbyte == 0x55) { state = 1; } if (startbyte == 0xAA && state == 1) { read = 1; // myPort.clear(); } if (startbyte == 0xBB && state == 1) { result = 1; // myPort.clear(); } } if (result == 1) { myPort.readBytes(score); print("person: " + score[0] + " no person: " + score[1] + "\n"); result = 0; } if (read ==1) { // read the saw bytes in myPort.readBytes(frameBuffer); // access raw bytes via byte buffer ByteBuffer bb = ByteBuffer.wrap(frameBuffer); bb.order(ByteOrder.BIG_ENDIAN); int i = 0; while (bb.hasRemaining()) { // read 16-bit pixel short p = bb.getShort(); int p1 = (p>>8)&0xFF; int p2 = p&0xFF; // convert RGB565 to RGB 24-bit int r = p1;//((p >> 11) & 0x1f) << 3; int g = p1;//((p >> 5) & 0x3f) << 2; int b = p1;//((p >> 0) & 0x1f) << 3; // set pixel color myImage .pixels[i++] = color(r, g, b); r = p2;//((p >> 11) & 0x1f) << 3; g = p2;//((p >> 5) & 0x3f) << 2; b = p2;//((p >> 0) & 0x1f) << 3; // set pixel color myImage .pixels[i++] = color(r, g, b); } read = 0; } myImage .updatePixels(); } |
確認したポート名でmyport を変更(Windows版をコメントアウトしてLinux版を採用するだけでOK)。
変更したpdeスクリプトを読み込むかコピー・ペーストして実行します。
もしカメラ画像がグレーのままの場合は、ボーレートを921600から115200に変更して再実行してみてください。
カメラで検出
かなり高い検出結果になりました。
でも、真っ暗な画面でも50%以上の値を示しています、大丈夫でしょうか?
画像はバストショットかちょっと引いた感じで検出率は上がります。
この段階ではPico のMicro-Bポートとラズパイを接続しているUSBケーブルは給電しかしていないのでモバイルバッテリに切り替えてもOKです。
Appendix
ラズパイでもChatAI を動かせるらしいライブラリ GGML についての記事
Leave a Reply