Converting image to black and white and use it as array

17,621

Solution 1

Your image is rotated because of an origin problem.

If you use this snippet, the image will not be rotated upside-down.

pl.imshow(im, origin='lower')
pl.show()

You could also simply use im.show() to display the image.

Now, back to the original question. I think the problem comes from the fact that pylab cannot handle bilevel images. You certainly want to use a greyscale image and thus do this

import pylab as pl
import matplotlib.cm as cm
import numpy as np
import Image

im = Image.open('your/image/path')
im_grey = im.convert('L') # convert the image to *greyscale*
im_array = np.array(im_grey)
pl.imshow(im_array, cmap=cm.Greys_r)
pl.show() 

Solution 2

The problem is in the way you convert the image into numpy array. If you look at what the outputs from the functions are this becomes clear

>> np.array(im_gray)
array([[False, False, False, ...,  True, False, False],
   [ True,  True,  True, ...,  True,  True, False],
   [ True,  True,  True, ...,  True,  True, False],
   ..., 
   [False, False, False, ..., False, False, False],
   [False, False, False, ..., False, False, False],
   [False, False, False, ..., False, False, False]], dtype=bool)

That can't be right. pl.imshow takes an array of floats uint8 or PIL image, not an array of booleans. So you need to do the conversion into an array more explicitly, making sure to

cols,rows = im_gray.size
pixels = list(im_gray.getdata())

# an indexer into the flat list of pixels
# head ranges from 0 to len(pixels) with step cols
# tail ranges from cols to len(pixels) with step cols
head_tail = zip(range(0,len(pixels)+1,cols),range(cols,len(pixels)+1,cols))
im_data = np.ndarray(shape=(cols,rows), dtype=np.uint8)

# extract each row of pixels and save it to the numpy array
for i,(head,tail) in enumerate(head_tail):
    im_data[i] = np.array(pixels[head:tail], dtype=np.uint8)

pl.imshow(im_data, cmap='bone')

The final pl.imshow requires you to define a colormap. The 'bone' colormap is black and white. I presume passing a PIL image into the functions defines the colormap automagically.

Share:
17,621
blueSurfer
Author by

blueSurfer

Just another guy studying computer science.

Updated on June 25, 2022

Comments

  • blueSurfer
    blueSurfer almost 2 years

    I'm trying to convert a colored image to a black and white one.

    The original image is the following:

    I have a few problems. First:

    import pylab as pl
    import Image
    
    im = Image.open('joconde.png')
    
    pl.imshow(im)
    pl.axis('off')
    pl.show()
    

    I get this:

    First result

    Why is it rotated? That's not the point but I'd like to know why.

    im_gray = im.convert('1')
    
    pl.imshow(im_gray)
    pl.show() 
    

    And here is the processed black and white image:

    Now everything looks working. But I need to use that image as a numpy array in order to do some image processing. All I have to do is this:

    import numpy as np
    
    im_arr = np.array(im_gray)
    
    pl.imshow(im_arr)
    pl.axis('off')
    pl.show()
    

    But I get this:

    Why is this happening? I tried also:

    im_arr = np.array(im_gray, dtype='float')
    

    or:

    im_arr = np.asarray(im_gray)
    

    But nothing seems working. Maybe the problem is in the show method but I don't know.