È possibile raggiungere questo obiettivo la creazione di una terza serie di DTYPE uint8, oltre a una serie bool (che insieme sono più efficienti in termini di memoria di un array uint16).
np.putmask
è utile per evitare un array temporaneo.
a = np.array([100, 200, 250], dtype=np.uint8)
b = np.array([50, 50, 50], dtype=np.uint8)
c = 255 - b # a temp uint8 array here
np.putmask(a, c < a, c) # a temp bool array here
a += b
Tuttavia, come @moarningsun sottolinea correttamente, una matrice bool batte la stessa quantità di memoria, come una matrice uint8, quindi questo non è necessariamente utile. È possibile risolvere questo evitando avere più di una temperatura matrice in un dato momento:
a = np.array([100, 200, 250], dtype=np.uint8)
b = np.array([50, 50, 50], dtype=np.uint8)
b = 255 - b # old b is gone shortly after new array is created
np.putmask(a, b < a, b) # a temp bool array here, then it's gone
a += 255 - b # a temp array here, then it's gone
Questo approccio scambia consumo di memoria per la CPU.
Un altro approccio è quello di precalculate tutti i risultati possibili, che è O (1) memoria aggiuntiva (cioè indipendente dalla dimensione degli array):
c = np.clip(np.arange(256) + np.arange(256)[..., np.newaxis], 0, 255).astype(np.uint8)
c
=> array([[ 0, 1, 2, ..., 253, 254, 255],
[ 1, 2, 3, ..., 254, 255, 255],
[ 2, 3, 4, ..., 255, 255, 255],
...,
[253, 254, 255, ..., 255, 255, 255],
[254, 255, 255, ..., 255, 255, 255],
[255, 255, 255, ..., 255, 255, 255]], dtype=uint8)
c[a,b]
=> array([150, 250, 255], dtype=uint8)
Questo approccio è la maggior parte della memoria -efficiente se i tuoi array sono molto grandi. Anche in questo caso, è costoso nel tempo di elaborazione, perché sostituisce l'aggiunta super veloce con l'indicizzazione a 2dim-array più lenta.
SPIEGAZIONE DI COME FUNZIONA
costruzione della matrice c
sopra fa uso di un trucco di trasmissione NumPy. L'aggiunta di una matrice di forma (N,)
e la matrice di forma (1,N)
trasmettono entrambi come (N,N)
-like, quindi il risultato è una matrice NxN di tutte le possibili somme. Quindi, lo tagliamo. Otteniamo un array 2dim che soddisfa: c[i,j]=min(i+j,255)
per ogni i, j.
Quindi ciò che rimane è usare la fantasia indicizzazione per afferrare i giusti valori.Lavorare con l'ingresso che hai fornito, accediamo:
c[([100, 200, 250] , [50, 50, 50])]
Il primo indice-array si riferisce alla prima debole, e la seconda per il 2 ° dim. Pertanto, il risultato è un array della stessa forma degli array di indici ((N,)
), costituito dai valori [ c[100,50] , c[200,50] , c[250,50] ]
.
Non conoscevo 'putmask', grazie per quello! Usando questa funzione, penso che 'a + = b' seguito da' np.putmask (a, a
@moarningsun Penso che tu abbia ragione. Tuttavia si basa sullo straripamento, che personalmente non mi sento perfettamente a mio agio con ... – shx2
@ moarningsun perché hai cancellato la tua risposta? Penso che sia una risposta decente e funziona – shx2