6.4. Dtypes¶
Le type d’élément d’un ndarray est son dtype. Le dtype détermine trois choses à la fois : combien d’octets chaque élément occupe, comment les octets sont interprétés et quelle plage de valeurs le tableau peut stocker. Choisir le bon dtype est la décision la plus importante qui affecte l’utilisation de la RAM sur la caméra.
6.4.1. Les dtypes pris en charge¶
numpy sur la caméra prend en charge un petit ensemble de dtypes :
dtype |
octets |
plage |
|---|---|---|
|
1 |
0 à 255 |
|
1 |
-128 à 127 |
|
2 |
0 à 65 535 |
|
2 |
-32 768 à 32 767 |
|
4 |
IEEE 754 simple précision |
|
1 |
|
Il n’y a pas de int32 ni de int64, et la version ulab d’OpenMV n’active pas le dtype optionnel complex.
Choisissez le type qui correspond au matériel qui a produit les données. Un échantillon ADC 8 bits demande uint8 ; un échantillon ADC 12 bits tient dans uint16 ; un pixel de luminance issu d’une caméra en niveaux de gris tient dans uint8 – ce qui économise quatre fois la RAM que coûterait le float par défaut.
6.4.2. Le dtype par défaut¶
Le dtype par défaut de chaque constructeur sur Créer des tableaux est float. Ce n’est que rarement ce que l’application souhaite lorsqu’elle manipule des données de capteur. Passez dtype= explicitement chaque fois que la largeur naturelle est plus petite
sensor = np.array(samples, dtype=np.uint16)
Réenvelopper un tableau d’entiers sans argument dtype= copie et convertit en float, ce qui coûte à la fois du temps et de la RAM. Lorsque la performance compte, nommez le dtype.
6.4.3. Le dtype d’un tableau existant¶
dtype relit le dtype du tableau sous la forme du code de type entier que le tableau porte en interne
a = np.array([1, 2, 3], dtype=np.uint8)
print(a.dtype) # 66 (the integer value of ``'B'``)
Les entiers de code de type correspondent aux constantes exposées sur le module numpy – numpy.uint8, numpy.int8, numpy.uint16, numpy.int16, numpy.float, numpy.bool – de sorte que comparer le dtype à la constante du module est la façon dont un script se ramifie selon ce qu’un tableau contient
if a.dtype == np.uint8:
... # uint8 branch
6.4.4. Règles de promotion (upcasting)¶
Deux tableaux de dtypes différents peuvent être opérandes du même opérateur. numpy choisit le type du résultat selon une courte table :
gauche |
droite |
résultat |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tous |
|
|
La ligne uint16 / int16 est directement promue en float car numpy sur la caméra n’a pas de dtype entier 32 bits.
Lorsqu’un opérateur binaire a un scalaire Python d’un côté, le scalaire est converti en un tableau à un seul élément du plus petit dtype adapté : 123 devient un tableau uint8, -1000 devient int16, un float Python devient float.
6.4.5. Le débordement entier reboucle¶
Les opérations sur deux tableaux du même dtype entier conservent ce dtype, même lorsque le résultat déborde. La retenue est silencieusement abandonnée
a = np.array([200, 200], dtype=np.uint8)
b = np.array([100, 100], dtype=np.uint8)
print(a + b)
Sortie
array([44, 44], dtype=uint8)
Le résultat est 300 mod 256 == 44. Lorsqu’un résultat intermédiaire a besoin de plus de plage que le dtype d’entrée ne le permet, effectuez d’abord une conversion
c = np.array(a, dtype=np.uint16) + b
# array([300, 300], dtype=uint16)
Cette règle s’applique à chaque opérateur entier – +, -, *, //, %, &, |, ^. Les tableaux de flottants ne débordent jamais (ils sont promus vers l’infini à la place), donc l’astuce de conversion n’est nécessaire que dans le cas entier.