Reputation: 5821
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:
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.
Upvotes: 9
Views: 21212
Reputation: 7180
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()
Upvotes: 6
Reputation: 13088
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.
Upvotes: 2