Aggiungi un array numpy selezionato dall'indice a un altro array numpy con indici sovrapposti

Nov 27 2020

Ho due array NumPy imageed warped_imagee indici array ix,iy. Ho bisogno di aggiungere imagea warped_imagetale che image[i,j]viene aggiunto a warped_image[iy[i,j],ix[i,j]]. Il codice seguente funziona se le coppie (iy[i,j], ix[i,j])sono uniche per tutti i,j. Ma quando non sono univoci, cioè quando 2 elementi da imagedevono essere aggiunti allo stesso elemento in warped_image, solo uno di essi viene aggiunto. Come posso aggiungere entrambi gli elementi da imageallo stesso elemento in warped_image?

Nota che non voglio usare alcun forloop. Voglio mantenerlo vettorializzato. Ho intenzione di convertire il codice in TensorFlow o PyTorch in futuro per utilizzare le funzionalità della GPU per questo. Questo perché ho centinaia di tali immagini e ogni immagine è di risoluzione Full HD.

import numpy
image = numpy.array([[246,  50, 101], [116,   1, 113], [187, 110,  64]])
iy = numpy.array([[1, 0, 2], [1, 1, 0], [2, 0, 2]])
ix = numpy.array([[0, 2, 1], [1, 2, 0], [0, 1, 2]])
warped_image = numpy.zeros(shape=image.shape)
warped_image[iy, ix] += image

>> warped_image
Out[31]: 
array([[  113., 110.,  50.],
       [246., 116.,   1.],
       [187., 101.,  64.]])
   

Nel caso precedente, gli indici sono unici e quindi l'output è quello previsto.

import numpy
image = numpy.array([[246,  50, 101], [116,   1, 113], [187, 110,  64]])
iy = numpy.array([[1, 0, 2], [1, 0, 2], [2, 2, 2]])
ix = numpy.array([[0, 2, 1], [1, 2, 0], [0, 1, 2]])
warped_image = numpy.zeros(shape=image.shape)
warped_image[iy, ix] += image

>> warped_image
Out[32]: 
array([[  0.,   0.,   1.],
       [246., 116.,   0.],
       [187., 110.,  64.]])
   

Uscita prevista:

array([[  0.,   0.,   51.],
       [246., 116.,   0.],
       [300., 211.,  64.]])
       

In questo caso, ci sono 3 coppie di indici che si sovrappongono e quindi fallisce. Ad esempio, image[0,1]e image[1,1]dovrebbe essere aggiunto gt warped_image[0,2]per dare un valore 51. Tuttavia solo uno di essi ( image[1,1]) viene aggiunto per dare un valore 1.

Contesto :
sto cercando di deformare un'immagine da view1 a view2. Ho calcolato quale pixel deve andare dove. In caso di pixel sovrapposti, devo prendere una media ponderata di essi. Quindi, ho bisogno di ottenere quanto sopra. Maggiori dettagli qui

Risposte

1 DaniMesejo Nov 27 2020 at 21:12

Usa numpy.add.at :

import numpy
image = numpy.array([[246,  50, 101], [116,   1, 113], [187, 110,  64]])
iy = numpy.array([[1, 0, 2], [1, 0, 2], [2, 2, 2]])
ix = numpy.array([[0, 2, 1], [1, 2, 0], [0, 1, 2]])
warped_image = numpy.zeros(shape=image.shape)

np.add.at(warped_image, (iy, ix), image)

print(warped_image)

Produzione

[[  0.   0.  51.]
 [246. 116.   0.]
 [300. 211.  64.]]