Python: How to write a single channel png file from numpy array?
Solution 1
Here is a solution using opencv / cv2
import cv2
myImg = np.random.randint(255, size=(200, 400)) # create a random image
cv2.imwrite('myImage.png',myImg)
Solution 2
PIL's Image.fromarray()
automatically determines the mode to use from the datatype of the passed numpy array, for example for an 8-bit greyscale image you can use:
from PIL import Image
import numpy as np
data = np.random.randint(256, size=(100, 100), dtype=np.uint8)
img = Image.fromarray(data) # uses mode='L'
This however only works if your array uses a compatible datatype, if you simply use data = np.random.randint(256, size=(100, 100))
that can result in a int64 array (typestr <i8
), which PIL can't handle.
You can also specify a different mode, e.g. to interpret a 32bit array as an RGB image:
data = np.random.randint(2**32, size=(100, 100), dtype=np.uint32)
img = Image.fromarray(data, mode='RGB')
Internally Image.fromarray()
simply tries to guess the correct mode and size and then invokes Image.frombuffer()
.
The image can then be saved as any format PIL
can handle e.g: img.save('filename.png')
Solution 3
You might want not to utilise OpenCV for simple image manipulation. As suggested, use PIL:
im = Image.fromarray(arr)
im.save("output.png", "PNG")
Have you tried this? What has failed here that led you to concluding that this is JPEG-only?
Related videos on Youtube
mcExchange
Updated on September 15, 2022Comments
-
mcExchange over 1 year
I want to write a single channel png image from a numpy array in python? In Matlab that would be
A = randi(100,100,255) imwrite(uint8(A),'myFilename.png','png');
I saw exampels using
from PIL import Image
andImage.fromarray()
but they are for jpeg and 3-channel pngs only it appears...I already found the solution using opencv, I will post it here. Hopefully it will shorten someone else's searching...
-
MaxNoe about 7 years
-
-
mcExchange about 7 yearsthis saves a 3 channel pnd, but I need a 1 channel png file
-
Pearley about 7 yearsThen you need your array to be of type uint8. im = Image.fromarray(arr.astype(numpy.uint8))