J. Castro
J. Castro

Reputation: 43

How to, given a 2D numpy arrayMatrix that contains "triplets" of RGB values generate an image?

You see, most of the posts that discuss image creation deal with a 3D Matrix[0][1][2] that effectively contains the necessary info to apply directly

img = Image.fromarray(Matrix, 'RGB')

However, I'm stuck with a massive matrix that has "3n" columns and "n" rows. As you might see, the "image" is coded in a fashion reminding me of P3/P6 formats:

[ 0 0 0 255 255 255 0 0 0
  0 0 0 255 255 255 0 0 0 
  255 255 255 0 0 0 255 255 255]

The above 2D matrix represents 3x3 "pixels", and using Image.fromarray produces an image full of holes. I've thinking of splitting it into three (!!!) 2 dimensional arrays and then using np.dstack but that sounds terribly inefficient as the code is dinamically generating thousands of matrices with large dimensions (700x2100) that need to be presented as images.

This is what I'm thinking of doing, btw:

R = np.zeros((Y, X), dtype = np.uint8) # Same for G & B
    for Row in range(Y):
        for Column in range(3*X):
            if Column % 3 == 0: # With Column-1 for G and -2 for B
                R[Row][Column/3] = 2DMatrix[Row][Column]
#After populating R, G, B
RGB0 = np.dstack([R, G, B])
img = Image.fromarray(RGB0, 'RGB')

Thanks!

Upvotes: 4

Views: 678

Answers (1)

wildwilhelm
wildwilhelm

Reputation: 5019

numpy.reshape should work for this. It's also important that the color values are 8-bit unsigned:

>>> import numpy as np

>>> a = [[0, 0, 0, 255, 255, 255, 0, 0, 0],
...      [0, 0, 0, 255, 255, 255, 0, 0, 0],
...      [255, 255, 255, 0, 0, 0, 255, 255, 255]]
>>> a = np.array(a)
>>> a.astype('u1').reshape((3,3,3))

array([[[  0,   0,   0],
        [255, 255, 255],
        [  0,   0,   0]],

       [[  0,   0,   0],
        [255, 255, 255],
        [  0,   0,   0]],

       [[255, 255, 255],
        [  0,   0,   0],
        [255, 255, 255]]], dtype=uint8)

>>> import PIL.Image
>>> i = PIL.Image.fromarray(a.astype('u1').reshape((3,3,3)), 'RGB')

This seems to work the way we would expect:

>>> i.size
(3, 3)
>>> i.getpixel((0,0))
(0, 0, 0)
>>> i.getpixel((1,0))
(255, 255, 255)
>>> i.getpixel((2,0))
(0, 0, 0)
>>> i.getpixel((0,1))
(0, 0, 0)
>>> i.getpixel((1,1))
(255, 255, 255)
>>> i.getpixel((2,1))
(0, 0, 0)
>>> i.getpixel((0,2))
(255, 255, 255)
>>> i.getpixel((1,2))
(0, 0, 0)
>>> i.getpixel((2,2))
(255, 255, 255)

Upvotes: 3

Related Questions