6.4. Dtypes

Tip elementa ndarray je njegov dtype. Dtype odjednom određuje tri stvari: koliko bajtova zauzima svaki element, kako se bajtovi tumače i koji raspon vrijednosti polje može pohraniti. Odabir ispravnog dtypea najvažnija je pojedinačna odluka koja utječe na potrošnju RAM-a na kameri.

6.4.1. Podržani dtypeovi

numpy na kameri podržava mali skup dtypeova:

dtype

bajtovi

raspon

uint8

1

0 do 255

int8

1

-128 do 127

uint16

2

0 do 65.535

int16

2

-32.768 do 32.767

float

4

IEEE 754 jednostruka preciznost

bool

1

True / False

Ne postoji int32 ni int64, a OpenMV-ova ulab verzija ne omogućuje opcionalni complex dtype.

Odaberite tip koji odgovara hardveru koji je proizveo podatke. 8-bitni ADC uzorak želi uint8; 12-bitni ADC uzorak stane u uint16; piksel svjetline iz kamere u sivim tonovima stane u uint8 – čime se štedi četiri puta više RAM-a nego što bi koštao zadani float.

6.4.2. Zadani dtype

Zadani dtype svakog konstruktora na Stvaranje polja je float. To je rijetko ono što aplikacija želi pri rukovanju podacima senzora. Eksplicitno proslijedite dtype= kad god je prirodna širina manja:

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

Ponovno omatanje cjelobrojnog polja bez argumenta dtype= kopira i pretvara u float, što troši i vrijeme i RAM. Kad su performanse važne, imenujte dtype.

6.4.3. Dtype postojećeg polja

dtype čita dtype polja kao cjelobrojni kod tipa koji polje interno nosi:

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

Cjelobrojni kodovi tipa odgovaraju konstantama izloženima u modulu numpynumpy.uint8, numpy.int8, numpy.uint16, numpy.int16, numpy.float, numpy.bool – pa je usporedba dtypea s konstantom modula način na koji skripta grana ovisno o tome što polje sadrži:

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

6.4.4. Pravila povišenja tipa

Dva polja različitih dtypeova mogu biti operandi istog operatora. numpy bira tip rezultata prema kratkoj tablici:

lijevo

desno

rezultat

uint8

int8

int16

uint8

int16

int16

uint8

uint16

uint16

int8

int16

int16

int8

uint16

uint16

uint16

int16

float

bilo koji

float

float

Redak uint16 / int16 povisuje se izravno na float jer numpy na kameri nema 32-bitni cjelobrojni dtype.

Kada binarni operator ima Python skalar na jednoj strani, skalar se pretvara u jednoelementno polje najmanjeg prikladnog dtypea: 123 postaje uint8 polje, -1000 postaje int16, a Python float postaje float.

6.4.5. Cjelobrojno prelijevanje se omata

Operacije nad dva polja istog cjelobrojnog dtypea zadržavaju taj dtype, čak i kada se rezultat prelije. Prijenos se tiho odbacuje:

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

Izlaz:

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

Rezultat je 300 mod 256 == 44. Kada međurezultat treba veći raspon nego što ulazni dtype dopušta, prvo pretvorite tip:

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

Ovo pravilo vrijedi za svaki cjelobrojni operator – +, -, *, //, %, &, |, ^. Float polja se nikada ne prelijevaju (umjesto toga povisuju se u beskonačnost), pa je trik s pretvaranjem potreban samo u cjelobrojnom slučaju.