PIL interpolation access

irond_will irond_will at yahoo.com
Tue Nov 30 14:18:40 EST 2004


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



More information about the Python-list mailing list