I think the answer is wrong. The Image.fromarray( ____ , 'L') function seems to only work properly with an array of integers between 0 and 255. I use the np.uint8 function for this.
You can see this demonstrated if you try to make a gradient.
import numpy as np
from PIL import Image
# gradient between 0 and 1 for 256*256
array = np.linspace(0,1,256*256)
# reshape to 2d
mat = np.reshape(array,(256,256))
# Creates PIL image
img = Image.fromarray(np.uint8(mat * 255) , 'L')
img.show()
Makes a clean gradient
vs
import numpy as np
from PIL import Image
# gradient between 0 and 1 for 256*256
array = np.linspace(0,1,256*256)
# reshape to 2d
mat = np.reshape(array,(256,256))
# Creates PIL image
img = Image.fromarray( mat , 'L')
img.show()
Has the same kind of artifacting.
Answer from Nathan on Stack OverflowI think the answer is wrong. The Image.fromarray( ____ , 'L') function seems to only work properly with an array of integers between 0 and 255. I use the np.uint8 function for this.
You can see this demonstrated if you try to make a gradient.
import numpy as np
from PIL import Image
# gradient between 0 and 1 for 256*256
array = np.linspace(0,1,256*256)
# reshape to 2d
mat = np.reshape(array,(256,256))
# Creates PIL image
img = Image.fromarray(np.uint8(mat * 255) , 'L')
img.show()
Makes a clean gradient
vs
import numpy as np
from PIL import Image
# gradient between 0 and 1 for 256*256
array = np.linspace(0,1,256*256)
# reshape to 2d
mat = np.reshape(array,(256,256))
# Creates PIL image
img = Image.fromarray( mat , 'L')
img.show()
Has the same kind of artifacting.
If I understood you question, you want to get a grayscale image using PIL.
If this is the case, you do not need to multiply each pixels by 255.
The following worked for me
import numpy as np
from PIL import Image
# Creates a random image 100*100 pixels
mat = np.random.random((100,100))
# Creates PIL image
img = Image.fromarray(mat, 'L')
img.show()
This is easily done with PIL/Pillow. Create a new grayscale image of the proper size, and convert each array value to the range 0-255 and copy it in. I added a resize at the end to make the pixels easier to see.
from PIL import Image
array1 = [[0.48, 0.4, 0.56, 0.32, 0.52],
[0.36, 0.56, 0.56, 0.68, 0.56],
[0.32, 0.72, 0.88, 0.44, 0.56],
[0.56, 0.64, 0.76, 0.52, 0.48],
[0.32, 0.88, 0.56, 0.52, 0.4 ]]
width1 = 5
height1 = 5
im = Image.new('L', (width1, height1))
pix = im.load()
for y in range(height1):
for x in range(width1):
pix[x, y] = int(array1[y][x] * 255.9999)
im = im.resize((width1 * 10, height1 * 10), resample=Image.NEAREST)
im.save(r'c:\temp\temp.png')

PIL can create a PIL Image directly from an array:
from PIL import Image
import numpy as np
# Make our randomness repeatable, and generate a 5x4 array of pixels
np.random.seed(42)
px = np.random.random((4,5))
That looks like this:
array([[0.37454012, 0.95071431, 0.73199394, 0.59865848, 0.15601864],
[0.15599452, 0.05808361, 0.86617615, 0.60111501, 0.70807258],
[0.02058449, 0.96990985, 0.83244264, 0.21233911, 0.18182497],
[0.18340451, 0.30424224, 0.52475643, 0.43194502, 0.29122914]])
Now multiply up by 255, convert to np.uint8 and make into PIL Image
p = Image.fromarray((px*255.9999).astype(np.uint8))
# We are finished, but enlarge for illustrative purposes
p = p.resize((50, 40), resample=Image.Resampling.NEAREST)
p.save('result.png')

matplotlib - How can I convert an RGB image into grayscale in Python? - Stack Overflow
How do I convert from grayscale to black and white?
python - Turning a Large Matrix into a Grayscale Image - Stack Overflow
python - PIL load RGB matrix of a grayscale image - Stack Overflow
How about doing it with Pillow:
from PIL import Image
img = Image.open('image.png').convert('L')
img.save('greyscale.png')
If an alpha (transparency) channel is present in the input image and should be preserved, use mode LA:
img = Image.open('image.png').convert('LA')
Using matplotlib and the formula
Y' = 0.2989 R + 0.5870 G + 0.1140 B
you could do:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
def rgb2gray(rgb):
return np.dot(rgb[...,:3], [0.2989, 0.5870, 0.1140])
img = mpimg.imread('image.png')
gray = rgb2gray(img)
plt.imshow(gray, cmap=plt.get_cmap('gray'), vmin=0, vmax=1)
plt.show()
You can also use scikit-image, which provides some functions to convert an image in ndarray, like rgb2gray.
from skimage import color
from skimage import io
img = color.rgb2gray(io.imread('image.png'))
Notes: The weights used in this conversion are calibrated for contemporary CRT phosphors: Y = 0.2125 R + 0.7154 G + 0.0721 B
Alternatively, you can read image in grayscale by:
from skimage import io
img = io.imread('image.png', as_gray=True)
Consider the following image:
Image
If you zoom in, you will observe that the picture contains pixels of the form (0,0,0,x) in RGBA format (I have used pillow to verify this btw). What I want to do is if the pixel's alpha is less than equal to 200, then write (0,0,0,0) at the pixel's place, and if it is greater than 200 then write (0,0,0,255) at the pixel's place.
Here's my code rn:
from PIL import Image
import numpy as np
def inp_gen(img_path):
im = Image.open(img_path, 'r')
pix_vals = list(im.getdata())
layer = [x[3] for x in pix_vals]
for j in layer:
if j <= 200:
layer[layer.index(j)] = 0
if j > 200:
layer[layer.index(j)] = 1
return layer
def render_img(img_data):
image_data = [(0,0,0,255*x) for x in img_data]
data = np.array(image_data, dtype=np.uint8).T
image = Image.fromarray(data)
image.show()
render_img(img_gen("Path to image in drive link on my PC"))Sadly, this does not give me the output I want:
Output
So what should I do now?
Your array of "binary values" is an array of bytes?
If so, you can do (using Pillow) after resizing it:
from PIL import Image
im = Image.fromarray(arr)
And then im.show() to see it.
If your array has only 0's and 1's (1-bit depth or b/w) you may have to multiply it to 255
im = Image.fromarray(arr * 255)
Here an example:
>>> arr = numpy.random.randint(0,256, 100*100) #example of a 1-D array
>>> arr.resize((100,100))
>>> im = Image.fromarray(arr)
>>> im.show()

Edit (2018):
This question was written in 2011 and Pillow changed ever since requiring to use the mode='L' parameter when loading with fromarray.
Also on comments below it was said arr.astype(np.uint8) was needed as well, but I have not tested it
Using PIL is not really needed, you can plot the array directly with pyplot (see below). To save to a file, you could use plt.imsave('fname.png', im).

Code below.
import numpy as np
import matplotlib.pyplot as plt
x = (np.random.rand(1754**2) < 0.5).astype(int)
im = x.reshape(1754, 1754)
plt.gray()
plt.imshow(im)
You can also use plt.show(im) to display image in new window.