6.1. なぜ配列か

Image クラスは、その上のすべてのメソッドがカメラのネイティブなピクセルバッファに対して単一の高速な呼び出しで直接動作するため、ピクセル処理に適したツールです。アプリケーションがフレームに対して行うことのほとんど -- しきい値処理、ブロブ検出、AprilTag 検出、エッジフィルタ -- はすでにそこにあります。

画像ライブラリが 公開していない のは、OpenMV アプリケーションが直面するその他の数値処理です。

  • ピクセルではないセンサーバッファ -- ADC サンプル、IMU(慣性計測ユニット)の各軸、マイクの音声、

  • 組み込みメソッドが返さない、画像から派生した数値 -- ヒストグラムの1列、2つのフレームのカスタムブレンド、カタログにないピクセルごとの変換、

  • 小規模な線形代数 -- レンズを補正するキャリブレーション行列、IMU を融合する回転、

  • 信号処理の数学 -- 振動バッファの周波数成分、センサー出力に適用される平滑化、分類器が入力として求める特徴ベクトル。

これらすべては同じ形を求めます。すべての要素に1つの操作が適用される数値のバッファです。Python の for ループはそれを書く明白な方法です:

for i in range(len(samples)):
    samples[i] = samples[i] * cal

ループは機能します。しかし遅くもあります。Python はインタープリタ言語であり、Python ループの各反復はインタープリタを1回実行するコストを伴います。samples を検索し、要素 i を読み、乗算し、書き戻し、ループカウンタを進め、ループ条件をチェックします。1000個のセンサーサンプルのバッファでは、これらのインタープリタコストが積み重なり、本質的には素早い操作に対して数十ミリ秒に達します。

そのオーバーヘッドは、スクリプトがバッファに触れるたびに食い込みます。QVGA グレースケールフレームは76,800ピクセルです。100 Hz の加速度計は1秒間に100個の3軸サンプルを供給します。マイクは64ミリ秒ごとに1024サンプルのバッファを満たします。これらのいずれかに対する純粋な Python の for ループは、数マイクロ秒で済むはずの仕事を数十ミリ秒かかるものに変えてしまい、画像サイズのバッファではさらにおよそ10倍長くなります。

6.1.1. ライブラリ関数はループより高速

解決策は、要素に対する Python ループの代わりに、操作をバッファ全体に対する単一の関数呼び出しとして表現することです。numpy はまさにそれです。すべての操作が、バッファを最初から最後まで一度走査する、すでに最適化された1つの関数である、配列数学のライブラリです。np.multiply(samples, cal)samples のすべての要素を cal で1回の呼び出しの中で乗算します -- ループが行ったのと同じ算術を、反復ごとのインタープリタコストなしで行います。Python ループとして数十ミリ秒かかった同じ1000要素の乗算が、numpy 呼び出しとしては数十マイクロ秒で済みます。

これは numpy が全面的に提供する取引です。合計、平均、sin、exp、行列乗算、信号処理プリミティブ -- それぞれがバッファ全体を一度に操作する単一のライブラリ関数です。引き換えに、データは numpy の配列型の中に存在しなければならず、操作は要素を一つずつではなく、その配列に対して表現されなければなりません。

6.1.2. なぜリストではだめなのか

Python の list は代わりにはなりません。リストはあらゆる種類のオブジェクトの混合を保持できます -- 整数、浮動小数点数、文字列、他のリスト -- そしてそれを読むライブラリ関数は、何らかの算術が行われる前に、各スロットを見て何が入っているかを調べ、値を取り出さなければなりません。そのスロットごとのオーバーヘッドこそ、Python ループが支払うコストそのものです。リストは高速な配列数学には適しません。

6.1.3. なぜ bytearray でも不十分なのか

bytearray は正しい です -- 1つの型付きバッファ、要素ごとに1バイト、すべてが1つの連続したブロックの中にあります。これはほとんどのバイト指向のペリフェラル API が返すものです。それに欠けているのは 数学 です。bytearray * 2 は各値を2倍にするのではなくバッファを繰り返し、bytearray + bytearray を要素ごとに行うことに意味のある解釈はありません。

型付きバッファと要素ごとの数学を組み合わせるデータ構造が ndarray です。ボックスの中に何があるか、そして各フィールドが高速パスの挙動をどう形作るかが、この章の残りが乗る土台です。