6.3. Créer des tableaux¶
Chaque exemple sur le reste de ces pages commence avec un ndarray déjà disponible. Cette page est le catalogue des façons dont ce tableau voit le jour. Il existe quatre familles de constructeurs :
À partir d’un itérable Python – la forme habituelle littéral / liste / tuple.
Pré-rempli à une forme donnée – des zéros, des uns, une valeur constante, une matrice identité.
Généré comme une séquence – des valeurs sur une plage ou régulièrement espacées.
Enveloppant un tampon déjà en RAM – le cas des périphériques.
Chaque constructeur prend un mot-clé dtype= et utilise par défaut float. Les données de capteur veulent presque toujours un dtype plus petit que la valeur par défaut.
Chaque exemple ci-dessous commence par
from ulab import numpy as np
6.3.1. À partir d’un itérable Python¶
array() construit un ndarray à partir de n’importe quel itérable de nombres
a = np.array([1, 2, 3, 4])
print(a)
Sortie
array([1.0, 2.0, 3.0, 4.0], dtype=float)
Les itérables imbriqués produisent des tableaux multidimensionnels. Les itérables internes doivent tous avoir la même longueur, sinon une ValueError est levée
m = np.array([[1, 2, 3],
[4, 5, 6]], dtype=np.uint8)
Un ndarray préexistant est aussi une entrée valide ; array() copie toujours. Pour éviter la copie lorsqu’elle n’est pas nécessaire, utilisez asarray()
b = np.asarray(a, dtype=np.float) # same dtype -> no copy
6.3.2. Pré-rempli à une forme donnée¶
Lorsque la forme cible est connue mais que le contenu ne l’est pas encore, allouez le tampon à l’avance et écrivez-y plus tard :
zeros()– rempli de zéros.ones()– rempli de uns.full()– rempli d’une valeur donnée.empty()– alias dezeros()(ulabne laisse pas le tampon non initialisé).eye()– matrice de type identitéN-par-Mavec des uns sur lak-ième diagonale.diag()– une matrice diagonale à partir d’un vecteur, ou la diagonale d’une matrice.
np.zeros((3, 3)) # 3x3 of zeros
np.ones(5, dtype=np.uint8) # length-5 vector of ones
np.full((2, 3), 7, dtype=np.int8) # 2x3, all 7
np.eye(4) # 4x4 identity
np.diag([1, 2, 3]) # 3x3, [1, 2, 3] on the diagonal
L’argument shape est soit un entier unique (pour un tableau 1-D), soit un tuple.
6.3.3. Généré comme une séquence¶
arange()– des valeurs régulièrement espacées comme la fonction intégréerange(), mais renvoyant toujours unndarraynp.arange(0, 10, 2) # array([0, 2, 4, 6, 8])linspace()–numpoints régulièrement espacés entre deux limites, la borne supérieure étant incluse lorsqueendpoint=Truenp.linspace(0, 1, num=11) # 0.0, 0.1, ..., 1.0logspace()– des points espacés géométriquement.startetstopsont des exposants, non des bornes ; le résultat va debase ** startàbase ** stopnp.logspace(0, 3, num=4) # 1.0, 10.0, 100.0, 1000.0meshgrid()– construit deux matrices de coordonnées à partir de deux tableaux 1-D afin qu’une fonction par pixelf(x, y)puisse être évaluée sur toute une grille en un seul appel vectorisé. Étant donné un vecteur x de longueurWet un vecteur y de longueurH,meshgridrenvoie deux matricesH-par-W:Xest le vecteur x répété sur chaque ligne,Yest le vecteur y répété sur chaque colonne, de sorte queX[i, j]est la coordonnée x etY[i, j]la coordonnée y de la cellule à la ligneiet à la colonnejx = np.arange(4) # [0, 1, 2, 3] y = np.arange(3) # [0, 1, 2] X, Y = np.meshgrid(x, y) # X = [[0, 1, 2, 3], # [0, 1, 2, 3], # [0, 1, 2, 3]] # Y = [[0, 0, 0, 0], # [1, 1, 1, 1], # [2, 2, 2, 2]]
f(X, Y)évalue ensuite la fonction sur chaque cellule de la grille en une seule expression. Une carte de distance par rapport au centre sur une trame(H, W), par exemple, s’écritnp.sqrt((X - cx)**2 + (Y - cy)**2)appliquée aux matrices renvoyées parmeshgrid().
6.3.4. Assemblage¶
concatenate() joint un tuple de tableaux le long d’un axe existant
a = np.array([[1, 2], [3, 4]], dtype=np.uint8)
b = np.array([[5, 6]], dtype=np.uint8)
np.concatenate((a, b), axis=0)
# array([[1, 2], [3, 4], [5, 6]], dtype=uint8)
Toutes les entrées doivent partager le même dtype et le même ndim, et correspondre sur chaque axe autre que celui de la jonction. concatenate() alloue un tableau neuf assez grand pour contenir toutes les entrées et y copie les données ; c’est donc l’outil adapté pour une jonction ponctuelle de tableaux qui existent déjà ; c’est le mauvais outil à l’intérieur d’une boucle de diffusion en continu, où le motif consiste à préallouer la destination une fois et à y écrire par affectation de tranches.
6.3.5. Envelopper un tampon existant¶
Le constructeur le plus utile sur une caméra est frombuffer(). Il réinterprète un tampon de type bytes existant comme un ndarray 1-D sans copier un seul octet
buf = bytearray(8)
audio = np.frombuffer(buf, dtype=np.int16)
# 4 int16 samples, sharing memory with buf
Les écritures via audio sont visibles dans buf et vice versa. Le dtype choisi doit diviser exactement la longueur du tampon.
offset= saute un en-tête au début du tampon ; count= limite le nombre d’éléments lus
np.frombuffer(buf, dtype=np.uint8, offset=2, count=4)
C’est le bon constructeur chaque fois qu’un périphérique remet à l’application un tampon brut – des échantillons ADC dans un bytearray, une charge utile extraite d’un SPI. Les octets que le périphérique a écrits sont le tableau.
Lorsqu’un périphérique écrit des valeurs multi-octets dans un ordre d’octets que le CPU de la caméra ne lit pas nativement, byteswap() inverse l’ordre des octets de chaque élément afin que les valeurs soient lues correctement. Il renvoie un nouveau tableau par défaut ; passer inplace=True modifie la source sur place.
frombuffer() ne gère que les dtypes que numpy lui-même définit. Pour les périphériques qui produisent des échantillons entiers 32 bits, from_int32_buffer() et consorts convertissent en float en une seule passe.
6.3.6. Troncature à l’affichage¶
L’affichage d’un grand tableau ne montre que ses premiers et derniers éléments, avec ... au milieu, afin que le terminal de l’IDE ne se remplisse pas de milliers de valeurs
>>> print(np.arange(1000, dtype=np.uint16))
array([0, 1, 2, ..., 997, 998, 999], dtype=uint16)
set_printoptions() remplace les seuils lorsque le débogage nécessite l’ensemble du tampon
np.set_printoptions(threshold=2000) # print up to 2000 elements in full
np.set_printoptions(edgeitems=10) # 10 items at each end, not 3
get_printoptions() relit les réglages courants sous forme de dict.