I'm using the Python Imaging Library for some very simple image manipulation, however I'm having trouble converting a greyscale image to a monochrome (black and white) image. If I save after changing the image to greyscale (convert('L')) then the image renders as you would expect. However, if I convert the image to a monochrome, single-band image it just gives me noise as you can see in the images below. Is there a simple way to take a colour png image to a pure black and white image using PIL / python?
from PIL import Image
import ImageEnhance
import ImageFilter
from scipy.misc import imsave
image_file = Image.open("convert_image.png") # open colour image
image_file= image_file.convert('L') # convert image to monochrome - this works
image_file= image_file.convert('1') # convert image to black and white
imsave('result_col.png', image_file)
yields
A PIL only solution for creating a bi-level (black and white) image with a custom threshold:
With just
you get a dithered image.
Because from PIL
convert("1")
return the value "True" or "False". Try to print it, will be show:[False, False, True]
with single bracket.Whereas the numpy array use double bracket like this
[[False, False, True]]
or[[0, 0, 1]]
, right?Another option (which is useful e.g. for scientific purposes when you need to work with segmentation masks) is simply apply a threshold:
It looks like this for
./binarize.py -i convert_image.png -o result_bin.png --threshold 200
:Judging by the results obtained by unutbu I conclude that scipy's
imsave
does not understand monochrome (mode 1) images.As Martin Thoma has said, you need to normally apply thresholding. But you can do this using simple vectorization which will run much faster than the for loop that is used in that answer.
The code below converts the pixels of an image into 0 (black) and 1 (white).