Adicione uma matriz numpy selecionada de índice a outra matriz numpy com índices sobrepostos

Nov 27 2020

Eu tenho duas matrizes numpy imagee warped_imagee índices matrizes ix,iy. Eu preciso adicionar imageao warped_imageque image[i,j]é adicionado warped_image[iy[i,j],ix[i,j]]. O código abaixo funciona se os pares (iy[i,j], ix[i,j])forem exclusivos para todos i,j. Mas quando eles não são únicos, ou seja, quando 2 elementos imageprecisam ser adicionados ao mesmo elemento em warped_image, apenas um deles é adicionado. Como posso adicionar os dois elementos de imageao mesmo elemento em warped_image?

Observe que não quero usar nenhum forloop. Quero manter isso vetorizado. Estou planejando converter o código para TensorFlow ou PyTorch no futuro para usar recursos de GPU para isso. Isso porque eu tenho centenas dessas imagens e cada imagem é de resolução 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.]])
   

Para o caso acima, os índices são únicos e, portanto, a saída é a esperada.

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.]])
   

Resultado esperado:

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

Neste caso, existem 3 pares de índices que se sobrepõem e, portanto, falha. Por exemplo, image[0,1]e image[1,1]deve gt adicionado para warped_image[0,2]fornecer um valor 51. No entanto, apenas um deles ( image[1,1]) é adicionado para fornecer um valor 1.

Contexto :
Estou tentando distorcer uma imagem de view1 para view2. Calculei qual pixel deve ir para onde. No caso de pixels sobrepostos, preciso tirar uma média ponderada deles. Então, eu preciso alcançar o acima. Mais detalhes aqui

Respostas

1 DaniMesejo Nov 27 2020 at 21:12

Use 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)

Resultado

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