Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add a index selected numpy array to another numpy array with overlapping indices

I have two numpy arrays image and warped_image and indices arrays ix,iy. I need to add image to warped_image such that image[i,j] is added to warped_image[iy[i,j],ix[i,j]]. The below code works if the pairs (iy[i,j], ix[i,j]) are unique for all i,j. But when they are not unique i.e. when 2 elements from image need to be added to the same element in warped_image, only one of them gets added. How can I add both elements from image to the same element in warped_image?

Note that, I don't want to use any for loops. I want to keep this vectorized. I'm planning to convert the code to TensorFlow or PyTorch in the future to use GPU capabilities for this. That's because, I have hundreds of such images and each image is of full HD resolution.

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

For the above case, indices are unique and hence the output is as expected.

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

Expected Output:

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

In this case, there are 3 pairs of indices which overlap and hence it fails. E.g. image[0,1] and image[1,1] should gt added to warped_image[0,2] to give a value 51. However only one of them (image[1,1]) gets added to give a value 1.

Context:
I'm trying to do warp an image from view1 to view2. I've computed which pixel has to go where. In case of overlapping pixels, I need to take a weighted average of them. So, I need to achieve the above. More details here

like image 580
Nagabhushan S N Avatar asked Mar 25 '26 17:03

Nagabhushan S N


1 Answers

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)

Output

[[  0.   0.  51.]
 [246. 116.   0.]
 [300. 211.  64.]]
like image 185
Dani Mesejo Avatar answered Mar 27 '26 05:03

Dani Mesejo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!