6.4. Dtype

ndarray の要素の型がその dtype です。dtype は3つのことを同時に決定します。各要素が占めるバイト数、それらのバイトをどう解釈するか、そして配列が格納できる値の範囲です。適切な dtype を選ぶことは、カメラ上の RAM 使用量に影響する最も重要な決断です。

6.4.1. サポートされている dtype

カメラ上の numpy は、少数の dtype をサポートしています。

dtype

バイト数

範囲

uint8

1

0 から 255

int8

1

-128 から 127

uint16

2

0 から 65,535

int16

2

-32,768 から 32,767

float

4

IEEE 754 単精度

bool

1

True / False

int32int64 は存在せず、OpenMV の ulab ビルドではオプションの complex dtype は有効化されていません。

データを生成したハードウェアに合った型を選びましょう。8ビットの ADC サンプルには uint8 が適し、12ビットの ADC サンプルは uint16 に収まり、グレースケールカメラからの輝度ピクセルは uint8 に収まります。これによりデフォルトの float を使う場合の4分の1の RAM で済みます。

6.4.2. デフォルトの dtype

配列の作成 にあるすべてのコンストラクタのデフォルト dtype は float です。これはセンサーデータを扱う際にアプリケーションが望むものであることはまれです。自然な幅がより小さい場合は、必ず dtype= を明示的に渡しましょう:

sensor = np.array(samples, dtype=np.uint16)

整数配列を dtype= 引数なしで再ラップすると、コピーが行われた うえに float へ変換されるため、時間も RAM も消費します。パフォーマンスが重要な場合は dtype を明示しましょう。

6.4.3. 既存の配列の dtype

dtype は、配列が内部に保持する整数の型コードとして、その配列の dtype を読み戻します:

a = np.array([1, 2, 3], dtype=np.uint8)
print(a.dtype)            # 66 (the integer value of ``'B'``)

型コードの整数は numpy モジュールで公開されている定数 -- numpy.uint8numpy.int8numpy.uint16numpy.int16numpy.floatnumpy.bool -- に一致します。したがって、dtype をモジュール定数と比較することで、スクリプトは配列が何を保持しているかに応じて分岐します:

if a.dtype == np.uint8:
    ...  # uint8 branch

6.4.4. アップキャストのルール

異なる dtype の2つの配列を同じ演算子のオペランドにできます。numpy は、短い表に従って結果の型を選びます。

結果

uint8

int8

int16

uint8

int16

int16

uint8

uint16

uint16

int8

int16

int16

int8

uint16

uint16

uint16

int16

float

任意

float

float

カメラ上の numpy には32ビット整数の dtype がないため、uint16 / int16 の行は直接 float に昇格します。

二項演算子の一方に Python のスカラーがある場合、そのスカラーは適合する 最小の dtype の単一要素配列に変換されます。123uint8 配列に、-1000int16 に、Python の floatfloat になります。

6.4.5. 整数のオーバーフローはラップする

同じ整数 dtype の2つの配列に対する演算は、結果がオーバーフローする場合でも その dtype を維持します。桁上がりは何も告げずに切り捨てられます:

a = np.array([200, 200], dtype=np.uint8)
b = np.array([100, 100], dtype=np.uint8)
print(a + b)

出力:

array([44, 44], dtype=uint8)

結果は 300 mod 256 == 44 になります。中間結果が入力 dtype の許す範囲を超える場合は、先にキャストしましょう:

c = np.array(a, dtype=np.uint16) + b
# array([300, 300], dtype=uint16)

このルールはすべての整数演算子 -- +-*//%&|^ -- に適用されます。float 配列は決してオーバーフローしません(代わりに無限大に昇格します)。したがってこのキャストのテクニックが必要なのは整数の場合だけです。