drali
drali

Reputation: 307

How to convert 1-channel numpy matrix to 4-channel monochromatic image

I am working on a pyqt project with numpy and cv2. Basically, I want to use a binary numpy mask (1024, 1024) to create a 4 channel monochromatic image (1024, 1024, 4), where all 1s from the mask are pink and all 0s are invisible. Then I convert the image and show it as overlay in my QScene to highlight some pixels in another image.

My current approach does the job, but is too slow and I'm sure that numpy provides something more convenient.

color = (255, 0, 238, 100)
r = (mask * color[0]).reshape((w*h))
g = (mask * color[1]).reshape((w*h))
b = (mask * color[2]).reshape((w*h))
a = (mask * color[3]).reshape((w*h))

rgba = np.dstack((r, g, b, a)).reshape((w, h, 4))
transposed = np.transpose(rgba, axes=[1, 0, 2])

Is there a better way to show a mask overlay? I don't insist on using numpy, however, it is important that I can set the color, as I will be needing several colors.

Upvotes: 2

Views: 737

Answers (1)

Divakar
Divakar

Reputation: 221554

Yes! Use NumPy broadcasting to clean it up and have a one-liner, like so -

transposed = mask.T[...,None]*color

Explanation:

  1. Use mask.T to do the np.transpose operation done at the end.
  2. Use [...,None] on the transposed array to basically push all its dimensions to the front and create a singleton dim (dim with length=1) as the last axis. For introducing this new axis, we have used an alias for np.newaxis - None. Thus, we would achieve broadcasting for the transposed array along its last axis aligned with the elements of color.
  3. Finally, we perform the element-wise multiplication itself, which in fact would be a broadcasted operation.

You can perform the creation of new axis part at the start and then use np.transpose or np.swapaxes and this would be closer to your original code. So, alternatively we could have :

transposed = mask[:,:,None].transpose(1,0,2)*color

and,

transposed = mask[:,:,None].swapaxes(0,1)*color

Upvotes: 3

Related Questions