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 |
|---|---|---|
|
1 |
da 0 a 255 |
|
1 |
da -128 a 127 |
|
2 |
da 0 a 65.535 |
|
2 |
da -32.768 a 32.767 |
|
4 |
IEEE 754 a precisione singola |
|
1 |
|
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 numpy – numpy.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 |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
qualsiasi |
|
|
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.