6.18. 画像と ndarray¶
Image クラスは、カメラネイティブなピクセル処理のための高速な表面です。このクラスのすべてのメソッドは、カメラのネイティブピクセル形式のフレームバッファ上で直接動作します。numpy は、それ以外のすべてを扱う汎用的な数値処理の表面です。この2つを橋渡しするメソッドが2つあります。
image.Image.to_ndarray()-- 画像のピクセルをndarrayにコピーします。image.Imageコンストラクタ --ndarrayから新しい画像を構築します。
この2つを組み合わせることで、アプリケーションはフレームをキャプチャし、それを numpy に渡してカスタム変換を行い、その結果を画像に戻して表示・保存したり、画像ライブラリの残りの処理に再び供給したりできます。
6.18.1. 画像から ndarray へ¶
to_ndarray() は新しい ndarray を割り当て、画像のピクセルデータを(以下の dtype マッピングに従って)そこにコピーします。これは決して画像のフレームバッファへのビューではありません。numpy 配列は常に自身のバイト列を所有します。シグネチャは to_ndarray(dtype, *, buffer=None) で、出力の形状は画像形式に依存します。
GRAYSCALE -- 2次元配列、形状
(height, width)。RGB565 -- 3次元配列、形状
(height, width, 3)、プレーンは R/G/B の順。
dtype 引数は、各8ビットピクセル値 v がどのようにマッピングされるかを制御します。
|
要素 |
8ビットピクセル値 |
|---|---|---|
|
|
|
|
|
|
|
|
|
例 -- グレースケールフレームを uint8 行列として表示する:
import csi
from ulab import numpy as np
csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.GRAYSCALE)
csi0.framesize(csi.QVGA)
img = csi0.snapshot()
a = img.to_ndarray('B') # shape (240, 320), dtype=uint8
print(a.shape, a.dtype)
print("mean brightness:", np.mean(a))
buffer= キーワードを使うと、アプリケーションが既に割り当てた bytearray を再利用できるため、カメラはフレームごとに新しいものを割り当てる必要がなくなります:
buf = bytearray(320 * 240)
while True:
img = csi0.snapshot()
a = img.to_ndarray('B', buffer=buf)
# ... process a ...
6.18.2. ndarray から画像へ¶
逆方向では、ndarray を image.Image の第1引数として渡します。コンストラクタは新しい画像バッファを割り当て、配列の値を 0..255 にクランプおよび丸めながらそこにコピーします:
image.Image(arr, *, buffer=None, copy_to_fb=False)
コンストラクタは、配列の形状からジオメトリとピクセル形式を推測します。
形状
(h, w)--GRAYSCALE画像。形状
(h, w, 3)--RGB565画像。
ndarray は dtype float である必要があります。コンストラクタは現時点ではこのケースのみをサポートしています。値は 0..255 の範囲に丸められ、クランプされます。
buffer= を使うと、アプリケーションは結果の画像用に既に割り当てた bytearray を供給できます。copy_to_fb=True は結果をカメラのフレームバッファに書き込みます。これは結果を IDE プレビューに表示したい場合に適切な選択です。
6.18.3. ラウンドトリップ¶
import csi
import image
from ulab import numpy as np
csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.GRAYSCALE)
csi0.framesize(csi.QVGA)
img = csi0.snapshot()
a = img.to_ndarray('f') # work in float space
a = 255.0 * (a / 255.0) ** 0.5 # gamma correction
out = image.Image(a, copy_to_fb=True) # back to an image
6.18.4. いつ橋渡しを使うか¶
この橋渡しは、組み込みの image メソッドが提供しない汎用的な数値演算(カスタムフィルタ、カスタムブレンド、特殊な非線形処理など)がアプリケーションに必要な場合、あるいはピクセルデータを非画像データ(IMU の各軸、オーディオサンプル)と1つの計算の中で組み合わせる必要がある場合に適切な答えです。
これは、Image クラスが既にカバーしている高スループットなピクセル処理には適切ではありません。組み込みメソッドはカメラのネイティブピクセル形式のフレームバッファ上で直接動作し、同等の numpy 式よりもはるかに高速です。画像ライブラリがまだ提供していない演算には、この橋渡しを活用してください。