Coolcrab
Coolcrab

Reputation: 2723

python make RGB image from 3 float32 numpy arrays

I have 3 arrays which are 400x600, which represent the 3 colors of the image i want to make.

I found a potential way here: http://docs.scipy.org/doc/scipy-0.13.0/reference/generated/scipy.misc.imsave.html but they want me to convert the floats to uint8's. Now if I change the dtype by 'image.dtype = np.uint8' then somehow changes the dimention to 400x600x24 (while when I don't change the type it is 400x600x3)

How do I change this? (Other methods also welcome)

Upvotes: 9

Views: 18878

Answers (2)

PatRiot
PatRiot

Reputation: 21

Thank you @abarnert! This was what i searched for to load an image from a dataset like sklearn.datasets.fetch_olivetti_faces(), which has dtype of float32 and Value ranges from 0-1 to work with OpenCV which uses a dtype of uint8 and Values ranging from 0-255.

import numpy as np
import cv2 as cv
from sklearn import datasets

data = datasets.fetch_olivetti_faces()
image = data.images[15]
image

array([[0.6694215 , 0.6818182 , 0.7066116 , ..., 0.5082645 , 0.55785125, 0.58677685], [0.677686 , 0.70247936, 0.71487606, ..., 0.5289256 , 0.5495868 , 0.58264464], [0.6983471 , 0.7107438 , 0.70247936, ..., 0.5495868 , 0.55785125, 0.5785124 ], ..., [0.59917355, 0.59917355, 0.54545456, ..., 0.10743801, 0.11157025, 0.10330579], [0.59090906, 0.6198347 , 0.5785124 , ..., 0.11157025, 0.10743801, 0.10743801], [0.5661157 , 0.6280992 , 0.59917355, ..., 0.11157025, 0.11157025, 0.10743801]], dtype=float32)

img = (image * 255).round().astype(np.uint8)
img

array([[171, 174, 180, ..., 130, 142, 150], [173, 179, 182, ..., 135, 140, 149], [178, 181, 179, ..., 140, 142, 148], ..., [153, 153, 139, ..., 27, 28, 26], [151, 158, 148, ..., 28, 27, 27], [144, 160, 153, ..., 28, 28, 27]], dtype=uint8)

The img is now ready for further processing in cv library.

Upvotes: 1

abarnert
abarnert

Reputation: 365767

image.dtype = np.uint8 just forcibly casts the bytes from float64 to uint8. Since each float64 takes 8 bytes, and each uint8 is only 1 byte, you're getting 8 times as many values.

To convert the values, instead of reinterpreting the bytes, you want the astype method:

image = image.astype(np.uint8)

However, that probably isn't going to be very useful, for two reasons. First, the big one, your float values are probably all in the range 0.0-1.0. Second, astype truncates, rather than rounding. So, converting to integers is just going to make almost all of them 0, and the rest 1, rather than smoothly ranging from 0-255.

So, what you probably want is something like:

image = (image * 255).round().astype(np.uint8)

Upvotes: 19

Related Questions