Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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:

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.

like image 310
blueSurfer Avatar asked Jul 31 '12 10:07

blueSurfer


People also ask

Can an image could be converted into a NumPy array?

Images are an easier way to represent the working model. In Machine Learning, Python uses the image data in the format of Height, Width, Channel format. i.e. Images are converted into Numpy Array in Height, Width, Channel format.

Why do we convert image to NumPy array?

Converting an image to an array is an important task to train a machine learning model based on the features of an image. We mainly use the NumPy library in Python to work with arrays so we can also use it to convert images to an array. Other than NumPy, we can also use the Keras library in Python for the same task.


2 Answers

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() 
like image 194
Balthazar Rouberol Avatar answered Sep 30 '22 11:09

Balthazar Rouberol


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.

like image 22
Matti Lyra Avatar answered Sep 30 '22 10:09

Matti Lyra