[PYTHON MATRIX-SIG] Naming Conventions And Practical Experience

Perry A. Stoll stoll@atr-sw.atr.co.jp
Thu, 08 Feb 1996 18:22:12 +0900


>>>>> "FL" == Fredrik Lundh <Fredrik_Lundh@ivab.se> writes:

    FL> would like to use the matrix extension to do some of the
    FL> serious processing stuff in my forthcoming Python Imaging
    FL> library, like FFTs and 2D convolutions.  Any ideas on how to
    FL> achieve this?

I'm working on something similar. I've got various FFT packages off
the net - I'll try to interface them, but I don't have time right
now. If you are interested in doing it, let me know.

In the mean time, for those wanting to play take a look at the file
attached at the end. It's not the stuff legends are made of, but it
should work.

-Perry


--------------------- cut here ------------------------------------
""" conv2 - support convolution of a 2 dimensional matrix by a 2
dimensional kernel. 

This routine was inspired by the matlab(c) version of conv2.

Sample usage:
>>> import conv2

# a sobel edge finding kernel
>>> sobel = Numeric.array([[1.0 ,2, 1],[0, 0, 0],[-1, -2, -1]])

# a test array
>>> A     = Numeric.zeros(10,10)
>>> S     = Numeric.Slice(2,8)
>>> A[(S,S)]  = 1

# do the convolution
>>> conv2.conv2(A,sobel)

"""

# Two dimension convolution for the Python Numeric package.
# Should be redone in C.
#
# questions to:
# Perry A. Stoll
# <stoll@atr-sw.atr.co.jp> or <pas@lems.brown.edu>


import Numeric,umath

class AddSlice(Numeric.Slice):
	def __init__(self, start=0, stop=None, step=1):
	     Numeric.Slice.__init__(self,start,stop, step)
	def __add__(self,x):
	     newslice = AddSlice(self.start,self.stop,self.step)
	     newslice.start = newslice.start + x
	     if newslice.stop != None:
		  newslice.stop = newslice.stop + x
	     return newslice
	__radd__ = __add__

class IncSlice(Numeric.Slice):
	def __init__(self, start=0, stop=None, step=1):
	     Numeric.Slice.__init__(self,start,stop,step)
	def inc(self):
 	     self.start = self.start + 1
	     if self.stop != None:
		  self.stop = self.stop + 1
     
def conv2(arg1,arg2,shape='full'):
     """ C = conv2(A, B) performs the 2-D convolution of matrices A and B.
     
If [ya,xa] == A.shape and [yb,xb] == B.shape, then 
C.shape == [ya+yb-1,xa+xb-1].
"""

     if (len(arg1.shape) != 2) or (len(arg2.shape) !=2):
	  raise TypeError, "both arguments must be 2 dimensional"

     # we always want to use the small matrix as arg2, 
     # so swap args if necessary
     swapped = 0
     Nmr = Numeric.multiply.reduce
     size1,size2 = Nmr(arg1.shape),Nmr(arg2.shape)

     if (size2 > size1):
	  swapped = 1
	  arg1,arg2 = arg2,arg1

     # unpack shape tuples
     (y1,x1),(y2,x2) = arg1.shape,arg2.shape

     # create output matrix
     out = Numeric.zeros(y2+y1-1,x2+x1-1)

     cols,rows = IncSlice(0,x2),IncSlice(0,y2)
     for j in range(0,y1):
	  rows.start,rows.stop = 0,y2
	  for i in range(0,x1):
	       w = arg1[j,i]
	       if w != 0:
		    out[cols,rows] = out[cols,rows] + w*arg2
	       rows.inc()
	  cols.inc()

     # not sure we need to do this...
     #if swapped:
	  #arg1,arg2 = arg2,arg1

     if (shape == 'full'):
	  pass
     elif (shape == 'same'):
	  rows = int(umath.floor(x2/2.0)) + AddSlice(0,x1)
	  cols = int(umath.floor(y2/2.0)) + AddSlice(0,y1)
	  out = out[cols,rows]
     elif (shape == 'valid'):
	  rows = x2 -1 + AddSlice(0,x1-x2 + 1)
	  cols = y2 -1 + AddSlice(0,y1-y2 + 1)
	  out = out[cols,rows]
     return out



=================
MATRIX-SIG  - SIG on Matrix Math for Python

send messages to: matrix-sig@python.org
administrivia to: matrix-sig-request@python.org
=================