简体   繁体   中英

Converting image to black and white and use it as array

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.

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM