You can just use the 3 argument form of np.where for this:
>>> import numpy as np
>>> x = np.array([1,2,31,32,4,0,3,0,0,0])
>>> z = np.array([99] * len(x))
>>> y = np.where(x != 0, x, z)
>>> y
array([ 1, 2, 31, 32, 4, 99, 3, 99, 99, 99])
Answer from mgilson on Stack OverflowYou can just use the 3 argument form of np.where for this:
>>> import numpy as np
>>> x = np.array([1,2,31,32,4,0,3,0,0,0])
>>> z = np.array([99] * len(x))
>>> y = np.where(x != 0, x, z)
>>> y
array([ 1, 2, 31, 32, 4, 99, 3, 99, 99, 99])
You're on the right track. Instead of using masked_where, you can find the values in x that aren't 0 using the != operator for ndarrays:
>>> import numpy as np
>>> x = np.array([1,2,31,32,4,0,3,0,0,0])
>>> y = x != 0 # create a boolean array of indices i where x[i] != 0
>>> y
array([ True, True, True, True, True, False, True, False, False, False], dtype=bool)
>>> z = np.array([99] * len(x))
>>> z
array([99, 99, 99, 99, 99, 99, 99, 99, 99, 99])
>>> z[y] = x[y]
>>> z
array([ 1, 2, 31, 32, 4, 99, 3, 99, 99, 99])
Why don't you use imshow instead?
You can plot a 2D image by doing:
plt.imshow(Image1, cmap='gray') # I would add interpolation='none'
Afterwards, you can easily overlay the segmentation by doing:
plt.imshow(Image2_mask, cmap='jet', alpha=0.5) # interpolation='none'
Changing the alpha will change the opacity of the overlay.
Additionaly, why do you create 2 masks? Only one should be enough, you can do:
Image2_mask = ma.masked_array(Image2 > 0, Image2)
Practical example:
import numpy as np
mask = np.zeros((10,10))
mask[3:-3, 3:-3] = 1 # white square in black background
im = mask + np.random.randn(10,10) * 0.01 # random image
masked = np.ma.masked_where(mask == 0, mask)
import matplotlib.pyplot as plt
plt.figure()
plt.subplot(1,2,1)
plt.imshow(im, 'gray', interpolation='none')
plt.subplot(1,2,2)
plt.imshow(im, 'gray', interpolation='none')
plt.imshow(masked, 'jet', interpolation='none', alpha=0.7)
plt.show()

Completing the Imanol Luengo's answer : masking image could be directly handled in imshow alpha option by putting an alpla image ie.
plt.imshow(Image1, cmap='gray') # I would add interpolation='none'
plt.imshow(Image2, cmap='jet', alpha=0.5*(Image2>0) ) # interpolation='none'
Your issue is trying to work with lists or object arrays.
Numpy is simply not designed for that. Use a flat array instead.
# convert subixs to a flat array
flat_subixs = np.concatenate(subixs)
# compute the lengths once
lengths = np.array([len(l) for l in subixs])
arr = np.repeat(overlay, lengths)
print(arr)
msk = (overlay == 1) | (overlay == 3)
arr[flat_subixs[np.repeat(msk, lengths)]] = np.repeat([44, 48, 47], lengths[msk])
print(arr)
Output:
[0 0 0 0 1 1 1 4 3]
[ 0 0 0 0 44 44 48 4 47]
This way all the slow computations (concatenation and lengths) are performed only once, and all other operations are vectorized.
If you want to mutate overlay this is also possible, just create arr once in the end:
msk = (overlay == 1) | (overlay == 3)
overlay[msk] = [44, 48, 47]
# eventually add other transforms here
# finally create "arr" once
arr = np.repeat(overlay, lengths)
print(arr)
# [ 0 0 0 0 44 44 48 4 47]
import numpy as np
new_value = [44, 48, 47]
msk = (overlay == 1) | (overlay == 3)
overlay[msk] = new_value
subixs = [[0, 1, 2, 3], [4, 5], [6], [7], [8]]
subixs = np.asarray(subixs, dtype=object)
arr_ixs = sum(subixs[msk], []) # Flatten the list of lists
# Get lengths of each selected sublist
lengths = np.array([len(lst) for lst in subixs[msk]])
# Repeat values accordingly
new_arr_value = np.repeat(new_value, lengths)
# Assign values
arr[arr_ixs] = new_arr_value
Explanation:
lengthsgives how many times each value should be repeated based on the size of the sublist.np.repeatvectorizes the expansion ofnew_valueto the desired length.This avoids any explicit Python loops for expansion.

