9

I'm trying to mask a 3D array (RGB image) with numpy.

However, my current approach is reshaping the masked array (output below). I have tried to follow the approach described on the SciKit-Image crash course. Crash Course

I have looked in the Stackoverflow and a similar question has been asked, but with no accepted answer (similar question here)

What is the best way to accomplish masking like this?

Here is my attempt:

# create some random numbers to fill array
tmp = np.random.random((10, 10))

# create a 3D array to be masked
a = np.dstack((tmp, tmp, tmp))

# create a boolean mask of zeros
mask = np.zeros_like(a, bool)

# set a few values in the mask to true
mask[1:5,0,0] = 1
mask[1:5,0,1] = 1

# Try to mask the original array
masked_array = a[:,:,:][mask == 1]

# Check that masked array is still 3D for plotting with imshow
print(a.shape)
(10, 10, 3)

print(mask.shape)
(10, 10, 3)

print(masked_array.shape)
(8,)

# plot original array and masked array, for comparison
plt.imshow(a)
plt.imshow(masked_array)

plt.show()
2
  • Are you trying to select values from the image, or to set parts of the image to zero using the mask? Would you like the mask to be 2D, and be applied to the color image, or 3D---one value in the mask for each value in the image? Commented Jun 26, 2017 at 15:37
  • I am trying to select parts of the image - it's a feature extraction problem in this case. Because I'm dealing with three-channel images, I assumed I need a 3D mask. However, a 2D mask is more appropriate, because the same pixel should be masked out on all three channels Commented Jun 27, 2017 at 19:47

2 Answers 2

8

NumPy broadcasting allows you to use a mask with a different shape than the image. E.g.,

import numpy as np
import matplotlib.pyplot as plt

# Construct a random 50x50 RGB image    
image = np.random.random((50, 50, 3))

# Construct mask according to some condition;
# in this case, select all pixels with a red value > 0.3
mask = image[..., 0] > 0.3

# Set all masked pixels to zero
masked = image.copy()
masked[mask] = 0

# Display original and masked images side-by-side
f, (ax0, ax1) = plt.subplots(1, 2)
ax0.imshow(image)
ax1.imshow(masked)
plt.show()

image masking

Sign up to request clarification or add additional context in comments.

Comments

2

After finding the following post on loss of dimensions HERE, I have found a solution using numpy.where:

masked_array = np.where(mask==1, a , 0)

This appears to work well.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.