Aly
Aly

Reputation: 16295

How to save a 3 channel numpy array as image

I have a numpy array with shape (3, 256, 256) which is a 3 channel (RGB) image of resoulution 256x256. I am trying to save this to disk with Image from PIL by doing the following:

from PIL import Image
import numpy as np

#... get array s.t. arr.shape = (3,256, 256)
img = Image.fromarray(arr, 'RGB')
img.save('out.png')

However this is saving an image of dimensions 256x3 to disk

Upvotes: 17

Views: 38111

Answers (3)

YuhaoQI
YuhaoQI

Reputation: 69

You can use opencv to do merge three channel and save as img.

import cv2
import numpy as np
arr = np.random.uniform(size=(3,256,256))*255 # It's a r,g,b array
img = cv2.merge((arr[2], arr[1], arr[0]))  # Use opencv to merge as b,g,r
cv2.imwrite('out.png', img) 

Upvotes: 0

Imanol Luengo
Imanol Luengo

Reputation: 15909

The @Dietrich answer is valid, however in some cases it will flip the image. Since the transpose operator reverses the index, if the image is stored in RGB x rows x cols the transpose operator will yield cols x rows x RGB (which is the rotated image and not the desired result).

>>> arr = np.random.uniform(size=(3,256,257))*255

Note the 257 for visualization purposes.

>>> arr.T.shape
(257, 256, 3)

>>> arr.transpose(1, 2, 0).shape
(256, 257, 3)

The last one is what you might want in some cases, since it reorders the image (rows x cols x RGB in the example) instead of fully transpose it.

>>> arr = np.random.uniform(size=(3,256,256))*255
>>> arr = np.ascontiguousarray(arr.transpose(1,2,0))
>>> img = Image.fromarray(arr, 'RGB')
>>> img.save('out.png')

Probably the cast to contiguous array is not even needed, but is better to be sure that the image is contiguous before saving it.

Upvotes: 22

Dietrich
Dietrich

Reputation: 5551

Try transposing arr which gives you an (256, 256, 3) array:

arr = np.random.uniform(size=(3,256,256))*255
img = Image.fromarray(arr.T, 'RGB')
img.save('out.png')

Upvotes: 10

Related Questions