Ethan
Ethan

Reputation: 1067

numpy-->PIL int type issue

So I've got the x and y values of a curve that I want to plot held as float values in numpy arrays. Now, I want to round them to the nearest int, and plot them as pixel values in an empty PIL image. Leaving out how I actually fill my x and y vectors, here is what we're working with:

# create blank image    
new_img = Image.new('L', (500,500))    
pix = new_img.load()

# round to int and convert to int    
xx = np.rint(x).astype(int)    
yy = np.rint(y).astype(int)

ordered_pairs = set(zip(xx, yy))

for i in ordered_pairs:    
    pix[i[0], i[1]] = 255  

This gives me an error message:

  File "makeCurves.py", line 105, in makeCurve
    pix[i[0], i[1]] = 255        
TypeError: an integer is required

However, this makes no sense to me since the .astype(int) should have cast these puppies to an integer. If I use pix[int(i[0]], int(i[1])] it works, but that's gross.

Why isn't my .astype(int) being recognized as int by PIL?

Upvotes: 4

Views: 2773

Answers (2)

Sam Mussmann
Sam Mussmann

Reputation: 5993

I think the problem is that your numpy arrays have type numpy.int64 or something similar, which PIL does not understand as an int that it can use to index into the image.

Try this, which converts all the numpy.int64s to Python ints:

# round to int and convert to int    
xx = map(int, np.rint(x).astype(int)) 
yy = map(int, np.rint(y).astype(int))

In case you're wondering how I figured this out, I used the type function on a value from a numpy array:

>>> a = np.array([[1.3, 403.2], [1.0, 0.3]])
>>> b = np.rint(a).astype(int)
>>> b.dtype
 dtype('int64')
>>> type(b[0, 0])
 numpy.int64
>>> type(int(b[0, 0]))
 int

Upvotes: 3

r_31415
r_31415

Reputation: 8980

Not sure what you're up to in the first part of your code, but why don't you replace pix = new_img.load() using this instead:

# create blank image    
new_img = Image.new('L', (500,500))

pix = array(new_img) # create an array with 500 rows and 500 columns

And then you can follow your original code:

# round to int and convert to int    
xx = np.rint(x).astype(int)    
yy = np.rint(y).astype(int)

ordered_pairs = set(zip(xx, yy))

for i in ordered_pairs:    
    pix[i[0], i[1]] = 255 

Out[23]: 
array([[  0,   0,   0, ...,   0,   0,   0],
       [  0, 255,   0, ...,   0,   0,   0],
       [  0,   0,   0, ...,   0,   0,   0],
       ..., 
       [  0,   0,   0, ...,   0,   0,   0],
       [  0,   0,   0, ...,   0,   0,   0],
       [  0,   0,   0, ...,   0,   0,   0]], dtype=uint8)

Upvotes: 2

Related Questions