6.4. Dtype

Il tipo degli elementi di un ndarray è il suo dtype. Il dtype stabilisce tre cose in una sola volta: quanti byte occupa ogni elemento, come vengono interpretati i byte e quale intervallo di valori l’array può memorizzare. Scegliere il dtype giusto è la singola decisione che più influisce sull’uso della RAM sulla camera.

6.4.1. I dtype supportati

numpy sulla camera supporta un piccolo insieme di dtype:

dtype

byte

intervallo

uint8

1

da 0 a 255

int8

1

da -128 a 127

uint16

2

da 0 a 65.535

int16

2

da -32.768 a 32.767

float

4

IEEE 754 a precisione singola

bool

1

True / False

Non esistono int32 o int64 e la build di ulab di OpenMV non abilita il dtype opzionale complex.

Scegli il tipo che corrisponde all’hardware che ha prodotto i dati. Un campione da un ADC a 8 bit vuole uint8; un campione da un ADC a 12 bit entra in uint16; un pixel di luminanza da una camera in scala di grigi entra in uint8 – risparmiando quattro volte la RAM che costerebbe il float predefinito.

6.4.2. Il dtype predefinito

Il dtype predefinito di ogni costruttore in Creare array è float. Raramente è ciò che l’applicazione desidera quando gestisce dati provenienti da sensori. Passa dtype= esplicitamente ogni volta che la larghezza naturale è inferiore:

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

Riavvolgere un array di interi senza un argomento dtype= copia e converte in float, il che costa sia tempo sia RAM. Quando le prestazioni contano, indica il dtype.

6.4.3. Il dtype di un array esistente

dtype restituisce il dtype dell’array come il codice di tipo intero che l’array porta internamente:

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

Gli interi del codice di tipo corrispondono alle costanti esposte nel modulo numpynumpy.uint8, numpy.int8, numpy.uint16, numpy.int16, numpy.float, numpy.bool – quindi confrontare il dtype con la costante del modulo è il modo in cui uno script si dirama in base a ciò che un array contiene:

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

6.4.4. Regole di promozione (upcasting)

Due array di dtype diversi possono essere operandi dello stesso operatore. numpy sceglie il tipo del risultato in base a una breve tabella:

sinistra

destra

risultato

uint8

int8

int16

uint8

int16

int16

uint8

uint16

uint16

int8

int16

int16

int8

uint16

uint16

uint16

int16

float

qualsiasi

float

float

La riga uint16 / int16 viene promossa direttamente a float perché numpy sulla camera non ha un dtype intero a 32 bit.

Quando un operatore binario ha uno scalare Python su un lato, lo scalare viene convertito in un array a elemento singolo del dtype adatto più piccolo: 123 diventa un array uint8, -1000 diventa int16, un float Python diventa float.

6.4.5. L’overflow degli interi avvolge

Le operazioni su due array dello stesso dtype intero mantengono quel dtype, anche quando il risultato va in overflow. Il riporto viene scartato silenziosamente:

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

Output:

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

Il risultato è 300 mod 256 == 44. Quando un valore intermedio necessita di un intervallo maggiore di quello consentito dal dtype di input, esegui prima il cast:

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

Questa regola si applica a ogni operatore intero – +, -, *, //, %, &, |, ^. Gli array float non vanno mai in overflow (vengono invece promossi a infinito), quindi il trucco del cast serve solo nel caso degli interi.