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 Overflowpython - Converting 2D Numpy array of grayscale values to a PIL image - Stack Overflow
python - How to change numpy array into grayscale opencv image - Stack Overflow
How to convert a numpy array to greyscale image? - 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()
As the assertion states, adaptiveThreshold() requires a single-channeled 8-bit image.
Assuming your floating-point image ranges from 0 to 1, which appears to be the case, you can convert the image by multiplying by 255 and casting to np.uint8:
float_img = np.random.random((4,4))
im = np.array(float_img * 255, dtype = np.uint8)
threshed = cv2.adaptiveThreshold(im, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 3, 0)
This one worked for me:
uint_img = np.array(float_arr*255).astype('uint8')
grayImage = cv2.cvtColor(uint_img, cv2.COLOR_GRAY2BGR)
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))
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.
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.
Here is a working code:
def grayConversion(image):
grayValue = 0.07 * image[:,:,2] + 0.72 * image[:,:,1] + 0.21 * image[:,:,0]
gray_img = grayValue.astype(np.uint8)
return gray_img
orig = cv2.imread(r'C:\Users\Jackson\Desktop\drum.png', 1)
g = grayConversion(orig)
cv2.imshow("Original", orig)
cv2.imshow("GrayScale", g)
cv2.waitKey(0)
cv2.destroyAllWindows()
You can use a dot product:
gray_image = image.dot([0.07, 0.72, 0.21])
Or even just do the whole operation manually:
b = image[..., 0]
g = image[..., 1]
r = image[..., 2]
gray_image = 0.21 * r + 0.72 * g + 0.07 * b
Don't forget to convert back to 0-255:
gray_image = np.min(gray_image, 255).astype(np.uint8)