PIL interpolation access

I

irond_will

Does anyone know how I might directly access PIL's bicubic
interpolator? I have an arbitrary array of points for which I need to
find interpolated color values. Unfortunately, I have no clue how to
acceess the bicubic filter in the PIL module, and my NumArray solution
is very slow and clunky.

I've hacked together a very very very slow solution that involves the
following steps:

1) import Image
2) translate Image to NumArray object (fairly slow)
3) find interpolated values for pixel array (breathtakingly slow)
4) translate interpolated color values (NumArray) into Image structure
(way too slow)

If anyone knows any way to perform items 2,3 or 4 with any facility,
please please please respond. The code I have now is extremely
clunky, largely due to my lack of facility with Python, Numarray and
PIL. Some is below:

I know I could speed up the algorithm by being smarter with vectors.
I don't really want to mess with this, though, if there's already a
better extant solution.

Thanks,

-Wm.

def bicub_interp(r,X):
from numarray import *
import Image
#r is the 2d array point in X space; this should be generalized to
take in an array of size [2,xspan,yspan]
#X is the graphic array. Its specifications are:
# dim 1 = x axis
# dim 2 = y axis
# dim 3 = [RGB] axis
# Each pixel of the X array is assumed to exist at the discrete
intersection of integer count.
# For instance, the bottom left point is X[0,0,:]

c_r_x = r.shape[1]
c_r_y = r.shape[2]
c_X_x = X.shape[0]
c_X_y = X.shape[1]
Y = zeros((c_r_x, c_r_y, 3))
for n_x in range(c_r_x):
for n_y in range(c_r_y):

r_x = r[0,n_x,n_y]
r_y = r[1,n_x,n_y]
r_i = int(r_x)
r_j = int(r_y)
r_dx = r_x - r_i
r_dy = r_y - r_y

if ( (0 < r_i < (c_X_x-2)) & (0 < r_j < (c_X_y-2)) ):
for n_m in range(-1,3):
for n_n in range(-1,3):
Y[n_x,n_y,:] += (X[r_i,r_j,:]
* Rfunc(n_m - r_dx)
* Rfunc(r_dy - n_n))
return Y

def Rfunc(X):
##For use in bicub_interp()
R = (1.0/6.0)*(1.0 * ((ramp(X+2.0))**3) -
4.0 * ((ramp(X+1.0))**3) +
6.0 * ((ramp(X ))**3) -
4.0 * ((ramp(X-1.0))**3))
return R

def ramp(X):
if (X<0): X = 0.0
return X

def image_to_array(im):

#This function returns an array of RGB pixel values
#The dimensions correspond as follows:
#Dim 1 = column or x value
#Dim 2 = row or y value
#Dim 3 = color value or [R,G,B] for [0, 1, 2]

#X.transpose operations can change the order of the axes if
desired.

X = vect_math.array_flip(transpose(reshape(array(im.getdata()),(im.size[1],im.size[0],3)),(1,0,2)),1)

return X

def array_to_image(X):
#SLOW method of mapping array of spects defined in image_to_array
into
#an image structure

#There is probably a faster way using im.putdata(), but I can't
figure out how to get the array structure
#oriented in such a fashion as to perform a direct put.

im = Image.new('RGB',(X.shape[0], X.shape[1]))
X=vect_math.array_flip(X,1)
for x in range(0,X.shape[0]):
for y in range(0,X.shape[1]):
im.putpixel((x,y),tuple(X[x,y,:]))
return im
 
I

irond_will

I managed to get steps 2 and 4 fixed (grabbing and putting the
pixels). I converted some code found at
http://effbot.org/zone/pil-numpy.htm written by Fredrick Lundh.
Currently, it only works for RBG bitmaps.

I'm certain that there are better ways to do some of this, but it's
pretty zippy as it stands. Now I really need to figure out the
bicubic interp, since that's the part that takes hours right now.


import image
import numarray

def image2numarray(im):

#This function returns an array of RGB pixel values
#The dimensions correspond as follows:
#Dim 1 = column or x value
#Dim 2 = row or y value
#Dim 3 = color value or [R,G,B] for [0, 1, 2]

if im.mode not in ("L", "F","RGB"):
raise ValueError, "Unsupported image type"
if im.mode == "L":
a = fromstring(im.tostring(), UInt8)
a.shape = im.size[1], im.size[0]
elif im.mode == "F":
a = fromstring(im.tostring(), Float32)
a.shape = im.size[1], im.size[0]
else:
a = fromstring(im.tostring(), UInt8)
a.shape = (im.size[1], im.size[0],3)

a.transpose((1,0,2))

return vect_math.array_flip(a,1)

def numarray2image(a):
#This function returns an array of RGB pixel values
#The dimensions correspond as follows:
#Dim 1 = column or x value
#Dim 2 = row or y value
#Dim 3 = color value or [R,G,B] for [0, 1, 2]
#The standard adopted here is that the lower-left corner is [0,0]

a = a.astype('UInt8')
b = vect_math.array_flip(a,1)
b.transpose((1,0,2))
return Image.fromstring('RGB', (b.shape[1], b.shape[0]),
b.tostring())

def array_flip(X,ndim):

#flips X along specified axis

return take(X,tuple(range(X.shape[ndim]-1,-1,-1)),axis=ndim)
 
C

Caleb Hattingh

Hi

I can't help you directly, but I am also finding im.putpixel to be
extremely slow - as the docs recommend, can you try using the
pixel-placing method of Draw? This is what I am going to try for my
application (resampling algorithms).

Thx
Caleb

Does anyone know how I might directly access PIL's bicubic
interpolator? I have an arbitrary array of points for which I need to
find interpolated color values. Unfortunately, I have no clue how to
acceess the bicubic filter in the PIL module, and my NumArray solution
is very slow and clunky.

I've hacked together a very very very slow solution that involves the
following steps:

1) import Image
2) translate Image to NumArray object (fairly slow)
3) find interpolated values for pixel array (breathtakingly slow)
4) translate interpolated color values (NumArray) into Image structure
(way too slow)

If anyone knows any way to perform items 2,3 or 4 with any facility,
please please please respond. The code I have now is extremely
clunky, largely due to my lack of facility with Python, Numarray and
PIL. Some is below:

I know I could speed up the algorithm by being smarter with vectors.
I don't really want to mess with this, though, if there's already a
better extant solution.

Thanks,

-Wm.

def bicub_interp(r,X):
from numarray import *
import Image
#r is the 2d array point in X space; this should be generalized to
take in an array of size [2,xspan,yspan]
#X is the graphic array. Its specifications are:
# dim 1 = x axis
# dim 2 = y axis
# dim 3 = [RGB] axis
# Each pixel of the X array is assumed to exist at the discrete
intersection of integer count.
# For instance, the bottom left point is X[0,0,:]

c_r_x = r.shape[1]
c_r_y = r.shape[2]
c_X_x = X.shape[0]
c_X_y = X.shape[1]
Y = zeros((c_r_x, c_r_y, 3))
for n_x in range(c_r_x):
for n_y in range(c_r_y):
r_x = r[0,n_x,n_y]
r_y = r[1,n_x,n_y]
r_i = int(r_x)
r_j = int(r_y)
r_dx = r_x - r_i
r_dy = r_y - r_y
if ( (0 < r_i < (c_X_x-2)) & (0 < r_j < (c_X_y-2)) ):
for n_m in range(-1,3):
for n_n in range(-1,3):
Y[n_x,n_y,:] += (X[r_i,r_j,:]
* Rfunc(n_m - r_dx)
* Rfunc(r_dy - n_n))
return Y

def Rfunc(X):
##For use in bicub_interp()
R = (1.0/6.0)*(1.0 * ((ramp(X+2.0))**3) -
4.0 * ((ramp(X+1.0))**3) +
6.0 * ((ramp(X ))**3) -
4.0 * ((ramp(X-1.0))**3))
return R

def ramp(X):
if (X<0): X = 0.0
return X

def image_to_array(im):

#This function returns an array of RGB pixel values
#The dimensions correspond as follows:
#Dim 1 = column or x value
#Dim 2 = row or y value
#Dim 3 = color value or [R,G,B] for [0, 1, 2]

#X.transpose operations can change the order of the axes if
desired.
X =
vect_math.array_flip(transpose(reshape(array(im.getdata()),(im.size[1],im.size[0],3)),(1,0,2)),1)
return X

def array_to_image(X):
#SLOW method of mapping array of spects defined in image_to_array
into
#an image structure

#There is probably a faster way using im.putdata(), but I can't
figure out how to get the array structure
#oriented in such a fashion as to perform a direct put.

im = Image.new('RGB',(X.shape[0], X.shape[1]))
X=vect_math.array_flip(X,1)
for x in range(0,X.shape[0]):
for y in range(0,X.shape[1]):
im.putpixel((x,y),tuple(X[x,y,:]))
return im
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,813
Latest member
lawrwtwinkle111

Latest Threads

Top