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.