Reputation: 1678
I have a numpy ndarray that looks something like:
[[0, 0.25, 1, ...., 0.5, 0.23 ],
[0.3, 0.75, 1, ..., 0.5, 0.37 ],
...,
...,
[0, 0.25, 1, ...., 0.5, 0.23 ],
[0.3, 0.75, 1, ..., 0.5, 0.37 ]]
Basically every value is in the range 0 - 1.0
I would like to visualize this as a bitmap and currently I have a very slow loop which basically does this:
for i, row in enumerate(data):
for j, val in enumerate(row):
yield val_to_rgb(val)
It then will take the 3-tuple of rgb components and do a PIL putdata on it and create a PNG.
I need to do this many times and this ghetto method is slow, and the colorization is very ugly.
My question is this:
Is there a series of matrix operations I can apply which will yield a colorized matrix containing the raw RGB values?
Which really consists of two questions:
Edit: Clarification- I'm looking to SAVE this as PNG, not just view it in real time. The reason being that a lot of this is getting executed on a headless machine which I then inspect after the fact.
The output of the current algo looks pretty nasty:
Upvotes: 2
Views: 417
Reputation: 13910
matplotlib has imshow function you can use out-of-the-box.
What you're doing is usually done via "vectorization". You define a function and let numpy do the iteration:
vec = np.vectorize(val_to_rgb)
rgb_data = vec(data)
Upvotes: 3
Reputation: 67467
I am not very familiar with PIL, but I am guessing that it will swallow a numpy array of shape (rows, cols, 3)
and turn it into an image. So you want to rewrite your val_to_rgb
function so that it works with arrays, not scalars, and places the RGB values in the last dimension of the shape.
E.g., say you wanted to interpret your values as grayscale, 0 being black, 1 being white. Your current function taking scalar inputs would look like this:
def val_to_rgb(val) :
return (int(val * 255),) * 3
and a vectorized form would be something like:
def vals_to_rgbs(vals) :
ret = np.zeros(vals.shape + (3,), dtype='uint8')
ret[...] = vals.reshape(vals.shape + (1,)) * 255
return ret
>>> vals_to_rgb(np.random.rand(10,10)).shape
(10, 10, 3)
>>> vals_to_rgb(np.random.rand(10,10)).dtype
dtype('uint8')
where the reshape is to have broadcasting do its magic.
Thinks can get more complicated, so if you need help vectorizing your specific val_to_rgb
function, post your code and I'll gladly take a shot at it.
Upvotes: 2