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')

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')

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.
matplotlib - How can I convert an RGB image into grayscale in Python? - Stack Overflow
python - Creating a good quality grayscale image from an multidimensional numpy array - Stack Overflow
python - How to change an image to grayscale represented as a NumPy array - Stack Overflow
python - how to save an array as a grayscale image with matplotlib/numpy? - Stack Overflow
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.
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()
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)
From what I understand, you're trying to display the numbers in your matrix as different shades of grey and make it large enough to fit on a poster. So, like @pandita, I would also use Matplotlib as this can be done pretty easily.
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np
height, width = 50, 33 #in pixels
spines = 'left', 'right', 'top', 'bottom'
labels = ['label' + spine for spine in spines]
tick_params = {spine : False for spine in spines}
tick_params.update({label : False for label in labels})
img = np.random.randint(0, 4097, (height, width))
img *= 255. / 4096
desired_width = 8 #in inches
scale = desired_width / float(width)
fig, ax = plt.subplots(1, 1, figsize=(desired_width, height*scale))
img = ax.imshow(img, cmap=cm.Greys_r, interpolation='none')
#remove spines
for spine in spines:
ax.spines[spine].set_visible(False)
#hide ticks and labels
ax.tick_params(**tick_params)
#preview
plt.show()
#save
fig.savefig('test.png', dpi=300)
Produces the following image ...

To summarize, you have 50x33 image and you want to upsize to get a "decent resolution/size to be able to put it on a poster."
This class of problem is called super-resolution. It is an active research area. Some super-resolution algorithms are available as part of the opencv library. opencv has a python port. You can read about the available super-resolution algorithms here.
Depending on the type of image that you have, achieving a nice-looking 640x480 resolution image starting from 50x33 could be a bit of a stretch for even the best algorithms. You may need to temper your goals.
Two issues. Firstly, you are not converting to greyscale. Secondly, the whole point of numpy is to vectorise and avoid for loops because they are slow.
So starting with this image:

You want something like this:
#!/usr/local/bin/python3
import numpy as np
from PIL import Image
# Load coins and convert to greyscale
grey = np.array(Image.open('coins.png').convert('L'))
# Threshold at 128
thresholded=((grey>128)*255).astype(np.uint8)
# Save
Image.fromarray(thresholded).save('result.png')

Sruthi V is right. enumerate() returns a tuple.
So instead of
if item < 128
it should be
if item[1] < 128
Or you could just remove enumerate() entirely if you aren't using it. It seems it will work fine without it.
With PIL it should work like this
from PIL import Image
I8 = (((I - I.min()) / (I.max() - I.min())) * 255.9).astype(np.uint8)
img = Image.fromarray(I8)
img.save("file.png")
There is also a possibility to use scikit-image, then there is no need to convert numpy array into a PIL object.
from skimage import io
io.imsave('output.tiff', I.astype(np.uint16))
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?