Reputation: 564
I am trying to use a large 2d array to create an image mask with black and transparent parts. Originally, the input 2d array was a PIL.Image
that was loaded in grayscale ('L'
) mode. So it contains values between 0 and 255. And now I want to replace all the 0s with [0,0,0,255]
(black stays black) and all values >0 should be [0,0,0,0]
(transparent). I can do this simply like this:
import numpy as np
# generate some random test data - normally I just read the input image, which is fast
input_data = np.array([np.array([random.choice([0,10]) for x in range(22000)]) for y in range(9000)])
# create a new img containing black and transparent pixels (r,g,b,alpha) and this takes ages
overlay_img = [[[0, 0, 0, 255] if input_data[y][x] == 0 else [0, 0, 0, 0] for x in range(len(input_data[0]))] for y in range(len(input_data))]
overlay_img = np.array(overlay_img)
This takes quite some time because the input data is so large (~22000x9000). I am curious if it is somehow possible to do this faster. I also tried np.where
, but I could not get it to work. Maybe there is even a way to directly change the PIL image?
fyi: In the end, I just want to plot this image on top of my matplotlib plot with imshow
, so that only the relevant regions are visible (where the image is transparent) and the rest is hidden/black.
Here just a very quick and small example of what I want to do:
Upvotes: 1
Views: 401
Reputation: 207465
I think you want this, but you haven't shown your code for imshow()
:
#!/usr/bin/env python3
import random
import numpy as np
# Set up dimensions and random input image
h, w = 9000, 22000
im = np.random.randint(0, 11, (h,w), dtype=np.uint8)
# Create 4-channel mask image
mask = np.zeros((h,w,4), dtype=np.uint8)
mask[...,3] = (im==0) * 255
The last line takes 800ms on my MacBook Pro.
If you need a bit more performance, you can use numexpr
as follows and the time required is 300ms instead of 800ms:
import random
import numexpr as ne
import numpy as np
# Set up dimensions and random input image
h, w = 9000, 22000
im = np.random.randint(0, 11, (h,w), dtype=np.uint8)
# Create 4-channel mask image
mask = np.zeros((h,w,4), dtype=np.uint8)
# Same but with "numexpr"
mask[...,3] = ne.evaluate("(im==0)*255")
Upvotes: 1