1

I have a 3D image which is a numpy array of shape (1314, 489, 3) and looks as follows:

RGB image

Now I want to calculate the mean RGB color value of the mask (the cob without the black background). Calculating the RGB value for the whole image is easy:

print(np.mean(colormaskcutted, axis=(0, 1)))
>>[186.18434633  88.89164511  46.32022921]

But now I want this mean RGB color value only for the cob. I have a 1D boolean mask array for the mask with this shape where one value corresponds to all of the 3 color channel values: (1314, 489)

I tried slicing the image array for the mask, as follows:

print(np.mean(colormaskcutted[boolean[:,:,0]], axis=(0, 1)))
>>124.57794089613752

But this returned only one value instead of 3 values for the RGB color.

How can I filter the 3D numpy image for a 1D boolean mask so that the mean RGB color calculation can be performed?

Olympia
  • 457
  • 8
  • 19

1 Answers1

2

If your question is limited to computing the mean, you don't necessarily need to subset the image. You can simply do, e.g.

np.sum(colormaskcutted*boolean[:,:,None], axis = (0,1))/np.sum(boolean)

P.S. I've played around with indexing, you can amend your original approach as follows:

np.mean(colormaskcutted[boolean,:], axis = 0)

P.P.S. Can't resist some benchmarking. So, the summation approach takes 15.9s (1000 iterations, dimensions like in the example, old computer); the advanced indexing approach is slightly longer, at 17.7s. However, the summation can be optimized further. Using count_nonzero as per Mad Physicist suggestion marginally improves the time to 15.3s. We can also use tensordot to skip creating a temporary array:

np.tensordot(colormaskcutted, boolean, axes = [[0,1], [0,1]])/np.count_nonzero(msk)  

This cuts the time to 4.5s.

Andrei
  • 2,585
  • 1
  • 14
  • 17