6.4. Dtypy¶
Typ prvků v ndarray je jeho dtype. Dtype rozhoduje o třech věcech najednou: kolik bajtů zabírá každý prvek, jak jsou bajty interpretovány a jaký rozsah hodnot může pole uchovávat. Volba správného dtype je jediným nejdůležitějším rozhodnutím, které ovlivňuje využití RAM na kameře.
6.4.1. Podporované dtypy¶
numpy na kameře podporuje malou sadu dtypů:
dtype |
bajty |
rozsah |
|---|---|---|
|
1 |
0 až 255 |
|
1 |
-128 až 127 |
|
2 |
0 až 65 535 |
|
2 |
-32 768 až 32 767 |
|
4 |
IEEE 754 jednoduchá přesnost |
|
1 |
|
Neexistuje int32 ani int64 a sestavení ulab od OpenMV nemá povolen volitelný dtype complex.
Vyberte typ, který odpovídá hardwaru, jenž data vyprodukoval. 8bitový vzorek z ADC chce uint8; 12bitový vzorek z ADC se vejde do uint16; jasový pixel z kamery ve stupních šedi se vejde do uint8 – což ušetří čtyřnásobek RAM oproti výchozímu float.
6.4.2. Výchozí dtype¶
Výchozím dtype každého konstruktoru na stránce Vytváření polí je float. To je málokdy to, co aplikace chce při práci s daty ze senzorů. Pokud je přirozená šířka menší, předávejte dtype= explicitně:
sensor = np.array(samples, dtype=np.uint16)
Opětovné zabalení celočíselného pole bez argumentu dtype= data zkopíruje a převede na float, což stojí čas i RAM. Když na výkonu záleží, dtype pojmenujte.
6.4.3. Dtype existujícího pole¶
dtype načte zpět dtype pole jako celočíselný kód typu, který si pole interně nese:
a = np.array([1, 2, 3], dtype=np.uint8)
print(a.dtype) # 66 (the integer value of ``'B'``)
Celá čísla kódů typů odpovídají konstantám vystaveným v modulu numpy – numpy.uint8, numpy.int8, numpy.uint16, numpy.int16, numpy.float, numpy.bool – takže porovnání dtype proti konstantě modulu je způsob, jak se skript větví podle toho, co pole obsahuje:
if a.dtype == np.uint8:
... # uint8 branch
6.4.4. Pravidla rozšiřování typů (upcasting)¶
Dvě pole různých dtypů mohou být operandy téhož operátoru. numpy vybírá výsledný typ podle krátké tabulky:
levý |
pravý |
výsledek |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
libovolný |
|
|
Řádek uint16 / int16 se rovnou povýší na float, protože numpy na kameře nemá 32bitový celočíselný dtype.
Když má binární operátor na jedné straně Python skalár, skalár se převede na jednoprvkové pole nejmenšího vhodného dtype: 123 se stane polem uint8, -1000 se stane int16, Python float se stane float.
6.4.5. Celočíselné přetečení přetéká (wrap)¶
Operace nad dvěma poli stejného celočíselného dtype tento dtype zachovají, i když výsledek přeteče. Přenos se tiše zahodí:
a = np.array([200, 200], dtype=np.uint8)
b = np.array([100, 100], dtype=np.uint8)
print(a + b)
Výstup:
array([44, 44], dtype=uint8)
Výsledkem je 300 mod 256 == 44. Když mezivýsledek potřebuje větší rozsah, než vstupní dtype dovoluje, nejprve proveďte přetypování:
c = np.array(a, dtype=np.uint16) + b
# array([300, 300], dtype=uint16)
Toto pravidlo platí pro každý celočíselný operátor – +, -, *, //, %, &, |, ^. Pole typu float nikdy nepřetečou (místo toho se povýší na nekonečno), takže trik s přetypováním je potřeba jen v celočíselném případě.