PIL interpolation access

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • irond_will

    #1

    PIL interpolation access

    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.arr ay_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
  • Caleb Hattingh

    #2
    Re: PIL interpolation access

    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

    On 30 Nov 2004 11:18:40 -0800, irond_will <irond_will@yah oo.com> wrote:
    [color=blue]
    > 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.arr ay_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[/color]

    Comment

    • irond_will

      #3
      Re: PIL interpolation access

      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, "Unsupporte d image type"
      if im.mode == "L":
      a = fromstring(im.t ostring(), UInt8)
      a.shape = im.size[1], im.size[0]
      elif im.mode == "F":
      a = fromstring(im.t ostring(), Float32)
      a.shape = im.size[1], im.size[0]
      else:
      a = fromstring(im.t ostring(), 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.fromstrin g('RGB', (b.shape[1], b.shape[0]),
      b.tostring())

      def array_flip(X,nd im):

      #flips X along specified axis

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

      "Caleb Hattingh" <caleb1@telkoms a.net> wrote in message news:<opsia6ht1 d1js0xs@news.te lkomsa.net>...[color=blue]
      > 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[/color]

      Comment

      Working...