title: What's wrong with my perspective transform coefficient function (Python)?
body: <p><strong>Original Question</strong></p>
  
  <p>So I've been reading up alot on how to do a Perspective transform on an image in pure Python but I can't get it to work. </p>
  
  <p>The transform itself is pretty simple, it's just a small equation, but I'm having trouble with the function for creating the coefficients from certain anchor points in the image. I've gotten a working code that completes without errors with the help of the excellent numpy-based answer <a href="https://stackoverflow.com/questions/14177744/how-does-perspective-transformation-work-in-pil">from another post</a>, but my issue is that I'm trying to do this in pure-Python. The coefficients turn out redicilously low, and nothing pops up on my resulting image. </p>
  
  <p>One issue could be in the porting of the numpy functions like dotmatrix, multiplication, and inverse matrix that I'm trying to do in pure Python functions. (I do get a perspective transformed image when I manually input each of the coefficients so I know the coefficient to rendering part should be working). So any help with figuring out what might be wrong with how I calculate the coefficients is greatly appreciated :)</p>
  
  <p><strong>Update</strong></p>
  
  <p>Alright, quick update, it turns out that the numpy code suddenly works now and produces what looks like a perspectived image (originally from the post I linked to earlier), so that's at least a good sign. Here is the exact numpy code I used, and thus the template of steps to be reproduced in pure Python. </p>
  
  <pre><code>import numpy
  matrix = []
  print pa,pb
  for p1, p2 in zip(pa, pb):
      matrix.append([p1[0], p1[1], 1, 0, 0, 0, -p2[0]*p1[0], -p2[0]*p1[1]])
      matrix.append([0, 0, 0, p1[0], p1[1], 1, -p2[1]*p1[0], -p2[1]*p1[1]])
  A = numpy.matrix(matrix, dtype=numpy.float)
  B = numpy.array(pb).reshape(8)
  print "ab",A,B
  res = numpy.dot(numpy.linalg.inv(A.T * A) * A.T, B)
  print "res",numpy.array(res).reshape(8)
  </code></pre>
  
  <p>And here is the pure Python version that currently attempts to reproduce the steps but fails:</p>
  
  <pre><code>def tilt(self, oldplane, newplane):
      """
      perspective transform.
      oldplane is a list of four old xy coordinate pairs
      that will move to the four points in the newplane
      """
      #first find the transform coefficients, thanks to https://stackoverflow.com/questions/14177744/how-does-perspective-transformation-work-in-pil
      pb,pa = oldplane,newplane
      grid = []
      for p1,p2 in zip(pa, pb):
          grid.append([p1[0], p1[1], 1, 0, 0, 0, -p2[0]*p1[0], -p2[0]*p1[1]])
          grid.append([0, 0, 0, p1[0], p1[1], 1, -p2[1]*p1[0], -p2[1]*p1[1]])
      def transpose(listoflists):
          return [list(each) for each in zip(*listoflists)]
      def flatten(listoflists):
          return [xory for xy in listoflists for xory in xy]
      def sumproduct(listA,multis):
          "aka, dot multiplication"
          outgrid = []
          for y,(row,multi) in enumerate(zip(listA,multis)):
              rowsum = 0
              for x,nr in enumerate(row):
                  rowsum += nr*multi
              outgrid.append(rowsum)
          return outgrid
      def gridmultiply(grid1,grid2):
          "aka, matrix*matrix"
          outgrid = []
          for y in xrange(len(grid1)):
              newrow = []
              for x in xrange(len(grid2)):
                  value = grid1[y][x] * grid2[y][x]
                  newrow.append(value)
              outgrid.append(newrow)
          return outgrid
      def gridinverse(grid):
          outgrid = []
          pos_deriv = 1
          neg_deriv = 1
          for y in xrange(len(grid)):
              horizline = []
              for x in xrange(len(grid[0])):
                  invx=len(grid[0])-1-x
                  invy=len(grid)-1-y
                  nr = grid[y][x]
                  pos_deriv += pos_deriv*nr
                  invnr = grid[invy][invx]*-1
                  horizline.append(invnr)
                  neg_deriv += neg_deriv*invnr
              outgrid.append(horizline)
          derivative = 1/float(pos_deriv-neg_deriv)
          print "deriv",derivative
          outgrid = gridmultiply(outgrid,[[derivative for _ in xrange(len(outgrid[0]))] for _ in xrange(len(outgrid))])
          return outgrid
  
      A = grid
      B = flatten(pb)
      res = sumproduct(gridinverse(gridmultiply(gridmultiply(transpose(A),A),transpose(A))), B)
      transcoeff = res
      print transcoeff
      #then calculate new coords, thanks to http://math.stackexchange.com/questions/413860/is-perspective-transform-affine-if-it-is-why-its-impossible-to-perspective-a"
      k = 1
      a,b,c,d,e,f,g,h = transcoeff
      outimg = Image().new(self.width,self.height)
      for y in xrange(len(self.imagegrid)):
          for x in xrange(len(self.imagegrid[0])):
              color = self.get(x,y)
              newx = int(round((a*x+b*y+c)/float(g*x+h*y+k)))
              newy = int(round((d*x+e*y+f)/float(g*x+h*y+k)))
              try:
                  outimg.put(newx,newy,color)
                  #print x,y,newx,newy
              except IndexError:
                  #out of bounds
                  pass
      return outimg
  </code></pre>