2

I'm trying to convert an array filled randomly with numbers (0,1,2) to an image where every number is shown as a different color (preferably picked by me if possible), but I can't find any way to do it. Is there someone who knows if it can be done?

I tried to use PIL but my tries are proving to be very unsatisfactory. I'd really appreciate if someone could help.


I got how to show it as an image, but I don't know how to randomize it. Let's say I have an array with dimensions 400x500 and I'd like to make every cell have one of the three values, can I do something like this? (most of this part of code is from a comment, it's not written by me)

from PIL import Image 
import numpy as np 

w, h = 500, 400 
a = [255, 0, 0]
b = [0, 255, 0]
c = [0, 0, 255]
data = np.array(np.random.random((a,b,c),(h, w, 3), dtype=np.uint8) 
#I'd like the random.random to take one of the three values ("[255, 0, 0]", "[0,255, 0]", or "[0, 0, 255]") 
img = Image.fromarray(data, 'RGB') 

img.save('my.png') 
img.show() 

Is there a way to do this?


I got it now, thank you for the help everybody!

ImTired
  • 35
  • 4
  • Is the problem converting a numpy matrix to a PIL image, or the process of making every pixel a different color? For the former, see https://stackoverflow.com/a/42096406/3015812. If the latter, can you add more about the array you're trying to use? Is it just an array, or is it two-dimensional? – HammerN'Songs Apr 01 '19 at 14:56
  • In the Spyder IDE you can simply double-click on an array in the variable explorer, to have a simple visualisation. – Dschoni Apr 01 '19 at 14:57
  • @HammerN'Songs It's a two-dimensional array, and I want to make it display an image that would have all the cells randomly colored with 3 different colors. The issue is that I either don't know how to randomly assign one of 3 values to every cell or after assigning how to display it as a picture – ImTired Apr 01 '19 at 15:19

4 Answers4

0

You could use PIL to create (and display) an image:

from PIL import Image
import numpy as np

w, h = 512, 512
data = np.zeros((h, w, 3), dtype=np.uint8)
data[256, 256] = [255, 0, 0]
img = Image.fromarray(data, 'RGB')
img.save('my.png')
img.show()
  • that would work, but the problem that I have is mainly with the fact that I'd like for the array to consist of cells that take one of the three values, be it "[255, 0, 0]", "[0,255, 0]", and "[0, 0, 255]". Is there a way to do this? to randomize which of the cells would have which value of the three? – ImTired Apr 01 '19 at 15:12
  • https://stackoverflow.com/questions/42096141/converting-a-numpy-array-to-a-pil-image/42096406#42096406 seems to have this answer for you – Tsvetomir Batinov Apr 01 '19 at 15:14
  • I still don't know how to randomize it though.. Let's say I have an array with dimensions 400x500 and I'd like to make every cell have one of the three values, can I do something like this? ``` from PIL import Image import numpy as np w, h = 500, 400 data = np.array(np.random.random((h, w, 3), dtype=np.uint8) #I'd like the random.random to take one of the three values ("[255, 0, 0]", "[0,255, 0]", and "[0, 0, 255]") img = Image.fromarray(data, 'RGB') img.save('my.png') img.show() ``` Is there a way to do this? – ImTired Apr 01 '19 at 15:28
0

So, there are two-three parts to this, and a few ways to go about it.

For simplicity, you could simply make a 2D numpy array of triples:

np.zeros((h, w, 3))

And then iterate over it, assigning each value to either (225, 0, 0), (0, 255, 0), or (0, 0, 255) depending on the value returned from a call to the random library.


More generically though, if you wanted an arbitrary number of colors and arbitrary assignment of those colors, I'd recommend something more like:

  1. Make a 2D array with random values from numpy.random.rand
  2. scale those values to however many colors you have, and convert to integers
  3. color each pixel in a new numpy array with the color corresponding to its number
  4. convert to PIL image
colorMapping = {
    0: (255, 0, 0),
    1: (0, 255, 0),
    2: (0, 0, 255),
    3: (255, 255, 0),
    4: (128, 42, 7),
    5: (128, 42, 7)
    # whatever colors you want. Could also use a list, but may be less clear.
}
w = #something
h = #something
numberOfColors = len(colorMapping)

randArray = np.random.rand(w, h)
scaledArray = randArray * numberOfColors
colorMapArray = scaledArray.astype(int)

# see [here][3] for sleeker, more elegant way of doing this
pixels = np.zeros((w, h, 3))
for i in range(0, w):
    for j in range(0, h):
        colorNumber = colorMapArray[i, j]
        pixels[(i, j)] = colorMapping[colorNumber]


im = Image.fromarray(pixels.astype('uint8'), 'RGB')
im.show()


In response to the edit:

You could do it like in that code example with minor changes, but you'd need to use one of the things in this question also linked above, for applying a function to every value in a 2D numpy array.

HammerN'Songs
  • 201
  • 3
  • 13
0

Maybe something like this?

import numpy as np

colors = [[255, 0, 0], [0, 255, 0], [0, 0, 255]]

# Make a mask for placing values
img = np.random.randint(0, num_colors, size=(256, 256))

color_img = np.zeros((img.shape[0], img.shape[1], 3), dtype='uint8')
color_img[img == 0, ...] = colors[0]
color_img[img == 1, ...] = colors[1]
color_img[img == 2, ...] = colors[2]
NanoBennett
  • 1,802
  • 1
  • 13
  • 13
0

You were very close with your code, you were just missing a Look Up Table (LUT) to look up the colour corresponding to your 0,1,2 data:

#!/usr/local/bin/python3
import numpy as np
from PIL import Image

# Specify image size, create and fill with random 0, 1, or 2
w, h = 500, 400 
data = np.random.randint(0,3,(h, w), dtype=np.uint8)

# Make LUT (Look Up Table) with your 3 colours
LUT = np.zeros((3,3),dtype=np.uint8)
LUT[0]=[255,0,0]
LUT[1]=[0,255,0]
LUT[2]=[0,0,255]

# Look Up each pixel in the LUT
pixels = LUT[data]

# Convert Numpy array to image, save and display
img = Image.fromarray(pixels) 
img.save('result.png')
img.show() 

enter image description here

Mark Setchell
  • 191,897
  • 31
  • 273
  • 432