title: Image perspective transform using Pillow
body: <p>I tried to draw bounding box of text on a image.The image 
  is perspective-transformed with a given set of coefficients. The coordinates of text before transformation is known, and I want to calculate the coordinates of text after transformation. </p>
  
  <p>To my understanding if I apply perspective transformation with the coefficients used in image transform to the text coordinates, I will get the resulting coordinates of the text after transformation. However, the text does not appear on the place it is supposed to be.</p>
  
  <p>See the following graphs 
  <a href="https://i.stack.imgur.com/pDf4s.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/pDf4s.jpg" alt="graph before transformation"></a></p>
  
  <p>The smaller white box bounds the text well because I know the coordinates of the text.</p>
  
  <p><a href="https://i.stack.imgur.com/pDf4s.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/Ug17A.jpg" alt="graph after transformation"></a></p>
  
  <p>The smaller white box is not bounding the text because of some error during transforming the coordinates.</p>
  
  <p>I follow the documentation<a href="http://effbot.org/imagingbook/image.htm" rel="nofollow noreferrer"> reference for coefficients of perspective transformation </a>
  and find the coefficients of image transformation using the following code:<a href="https://stackoverflow.com/questions/14177744/how-does-perspective-transformation-work-in-pil/24088499#24088499">origin of the code is from this answer</a></p>
  
  <pre><code>def find_coeffs(pa, pb):
      '''
      find the coefficients for perspective transform. 
  
      parameters:
          pa : verticies in the resulting plane
          pb : verticies in the current plane
  
      retrun:
          coeffs : 8- tuple
            coefficents for PIL perspective transform
      '''
      matrix = []
      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 = np.matrix(matrix, dtype=np.float)
      B = np.array(pb).reshape(8)
      res = np.dot(np.linalg.inv(A.T * A) * A.T, B)
      return np.array(res).reshape(8)
  </code></pre>
  
  <p>My code for text bounding box transformation:</p>
  
  <pre><code>    # perspective transformation
      a, b, c, d, e, f, g, h = coeffs
      # return two vertices defining the bounding box
  
      new_x0 = float(a * new_x0 - b * new_y0 + c) / float(g * new_x0 + h * new_y0 + 1)
      new_y0 = float(d * new_x0 + e * new_y0 + f) / float(g * new_x0 + h * new_y0 + 1)
      new_x1 = float(a * new_x1 - b * new_y1 + c) / float(g * new_x1 + h * new_y1 + 1)
      new_y1 = float(d * new_x1 + e * new_y1 + f) / float(g * new_x1 + h * new_y1 + 1) 
  </code></pre>
  
  <p>I also went to Pillow Github, but I could not find the source code where perspective transformation is defined.</p>
  
  <p>Some more info about the math of perspective transformation.<a href="https://www.math.utah.edu/~treiberg/Perspect/Perspect.htm" rel="nofollow noreferrer"> The Geometry of Perspective Drawing on the Computer </a></p>
  
  <p>Thanks.</p>