title: Implementing my own algorithm to scale and rotate images in python
body: <p>I am trying to implement an algorithm in python to scale images by a factor or rotate them by a given angle (or both at the same time). I am using opencv to handle the images and I know opencv has these functions built in, however I want to do this myself to better understand image transformations. I believe I calculate the rotation matrix correctly. However, when I try to implement the affine transformation, it does not come out correctly. </p>
  
  <pre><code>import numpy as np 
  import cv2
  import math as m 
  import sys
  
  img = cv2.imread(sys.argv[1])
  angle = sys.argv[2]
  
  #get rotation matrix
  def getRMat((cx, cy), angle, scale):
      a = scale*m.cos(angle*np.pi/180)
      b = scale*(m.sin(angle*np.pi/180))
      u = (1-a)*cx-b*cy
      v = b*cx+(1-a)*cy
      return np.array([[a,b,u], [-b,a,v]]) 
  
  #determine shape of img
  h, w = img.shape[:2]
  #print h, w
  #determine center of image
  cx, cy = (w / 2, h / 2)
  
  #calculate rotation matrix 
  #then grab sine and cosine of the matrix
  mat = getRMat((cx,cy), -int(angle), 1)
  print mat
  cos = np.abs(mat[0,0])
  sin  = np.abs(mat[0,1])
  
  #calculate new height and width to account for rotation
  newWidth = int((h * sin) + (w * cos))
  newHeight = int((h * cos) + (w * sin))
  #print newWidth, newHeight
  
  mat[0,2] += (newWidth / 2) - cx
  mat[1,2] += (newHeight / 2) - cy
  
  #this is how the image SHOULD look
  dst = cv2.warpAffine(img, mat, (newWidth, newHeight))
  
  cv2.imshow('dst', dst)
  cv2.waitKey(0)
  cv2.destroyAllWindows()
  
  #apply transform
  #attempt at my own warp affine function...still buggy tho
  def warpAff(image, matrix, (width, height)):
      dst = np.zeros((width, height, 3), dtype=np.uint8)
      oldh, oldw = image.shape[:2]
      #print oldh, oldw
      #loop through old img and transform its coords
      for x in range(oldh):
          for y in range(oldw):
              #print y, x
              #transform the coordinates
              u = int(x*matrix[0,0]+y*matrix[0,1]+matrix[0,2])
              v = int(x*matrix[1,0]+y*matrix[1,1]+matrix[1,2])
              #print u, v
              #v -= width / 1.5
              if (u &gt;= 0 and u &lt; height) and (v &gt;= 0 and v &lt; width):
                  dst[u,v] = image[x,y]
      return dst
  
  
  dst = warpAff(img, mat, (newWidth, newHeight))
  
  cv2.imshow('dst', dst)
  cv2.waitKey(0)
  cv2.destroyAllWindows()
  </code></pre>
  
  <p><a href="https://i.stack.imgur.com/3iheu.jpg" rel="noreferrer">Image I am using for testing</a></p>