Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get an array from RGB values of a bitmap image?

Tags:

python

pillow

I am running this code

from PIL import Image
import numpy as np
im = Image.open("/Users/Hugo/green_leaves.jpg")
im.load()
height, widht = im.size
p = np.array([0,0,0])
for row in range(height):
     for col in range(widht):
         a = im.getpixel((row,col))
         p = np.append(a.asarray())

But I am getting the following error

Traceback (most recent call last):
   File "/Users/hugo/PycharmProjects/Meteo API/image.py", line 17, in <module>
     p = np.append(a.asarray())
 AttributeError: 'tuple' object has no attribute 'asarray'

Could you help me?

like image 567
Hugo Avatar asked Feb 19 '14 15:02

Hugo


2 Answers

You mentioned numpy. If you want a numpy array of the image, don't iterate through it, just do data = np.array(im).

E.g.

from PIL import Image
import numpy as np
im = Image.open("/Users/Hugo/green_leaves.jpg")
p = np.array(im)

Building up a numpy array by repeatedly appending to it is very inefficient. Numpy arrays aren't like python lists (python lists serve that purpose very well!!). They're fixed-size, homogenous, memory-efficient arrays.

If you did want to build up a numpy array through appending, use a list (which can be efficiently appended to) and then convert that list to a numpy array.

However, in this case, PIL images support being converted to numpy arrays directly.

On one more note, the example I gave above isn't 100% equivalent to your code. p will be a height by width by numbands (3 or 4) array, instead of a numpixels by numbands array as it was in your original example.

If you want to reshape the array into numpixels by numbands, just do:

p = p.reshape(-1, p.shape[2])

(Or equivalently, p.shape = -1, p.shape[2])

This will reshape the array into width*height by numbands (either 3 or 4, depending on whether or not there's an alpha channel) array. In other words a sequence of the red,green,blue,alpha pixel values in the image. The -1 is a placeholder that tells numpy to calculate the appropriate shape for the first axes based on the other sizes that are specified.

like image 136
Joe Kington Avatar answered Oct 13 '22 12:10

Joe Kington


Initialize p as a list, and convert it to a numpy array after the for-loop:

p=[]
for row in range(height):
     for col in range(widht):
         a = im.getpixel((row,col))
         p.append(a)
p=np.asarray(p)

This will create a list of shape (*, 3), which is same as np.array(im).reshape(-1, 3). So if you need this, just use the latter form ;)

like image 30
zhangxaochen Avatar answered Oct 13 '22 12:10

zhangxaochen