title: Rotate image and crop out black borders
body: <p>My application: I am trying to rotate an image (using OpenCV and Python)</p>
  
  <p><img src="https://i.stack.imgur.com/KWoeo.jpg" alt="Rotating Images"></p>
  
  <p>At the moment I have developed the below code which rotates an input image, padding it with black borders, giving me A. What I want is B - the largest possible area crop window within the rotated image. I call this the axis-aligned boundED box.</p>
  
  <p>This is essentially the same as <a href="https://stackoverflow.com/questions/16255037/rotate-and-crop">Rotate and crop</a>, however I cannot get the answer on that question to work. Additionally, that answer is apparently only valid for square images. My images are rectangular.</p>
  
  <p>Code to give A:</p>
  
  <pre><code>import cv2
  import numpy as np
  
  
  def getTranslationMatrix2d(dx, dy):
      """
      Returns a numpy affine transformation matrix for a 2D translation of
      (dx, dy)
      """
      return np.matrix([[1, 0, dx], [0, 1, dy], [0, 0, 1]])
  
  
  def rotateImage(image, angle):
      """
      Rotates the given image about it's centre
      """
  
      image_size = (image.shape[1], image.shape[0])
      image_center = tuple(np.array(image_size) / 2)
  
      rot_mat = np.vstack([cv2.getRotationMatrix2D(image_center, angle, 1.0), [0, 0, 1]])
      trans_mat = np.identity(3)
  
      w2 = image_size[0] * 0.5
      h2 = image_size[1] * 0.5
  
      rot_mat_notranslate = np.matrix(rot_mat[0:2, 0:2])
  
      tl = (np.array([-w2, h2]) * rot_mat_notranslate).A[0]
      tr = (np.array([w2, h2]) * rot_mat_notranslate).A[0]
      bl = (np.array([-w2, -h2]) * rot_mat_notranslate).A[0]
      br = (np.array([w2, -h2]) * rot_mat_notranslate).A[0]
  
      x_coords = [pt[0] for pt in [tl, tr, bl, br]]
      x_pos = [x for x in x_coords if x &gt; 0]
      x_neg = [x for x in x_coords if x &lt; 0]
  
      y_coords = [pt[1] for pt in [tl, tr, bl, br]]
      y_pos = [y for y in y_coords if y &gt; 0]
      y_neg = [y for y in y_coords if y &lt; 0]
  
      right_bound = max(x_pos)
      left_bound = min(x_neg)
      top_bound = max(y_pos)
      bot_bound = min(y_neg)
  
      new_w = int(abs(right_bound - left_bound))
      new_h = int(abs(top_bound - bot_bound))
      new_image_size = (new_w, new_h)
  
      new_midx = new_w * 0.5
      new_midy = new_h * 0.5
  
      dx = int(new_midx - w2)
      dy = int(new_midy - h2)
  
      trans_mat = getTranslationMatrix2d(dx, dy)
      affine_mat = (np.matrix(trans_mat) * np.matrix(rot_mat))[0:2, :]
      result = cv2.warpAffine(image, affine_mat, new_image_size, flags=cv2.INTER_LINEAR)
  
      return result
  </code></pre>