title: Cropping an image after detecting the corners using opencv python
body: <p>I'm new one to openCV and computer-vision. Just now i'm trying to crop the Tiff scan after detecting the corners and then extract information from it based on exact coordinates x:y using python, openCV, numpy and OCR with Tesseract.</p>
  
  <p>What i achieved right now is that i upload an image (scan), binarize it, fix rotation and remove empty spaces. Result is already good, but not good enough. My image is still always rotated little bit. Here is image example <a href="https://i.stack.imgur.com/8mODm.jpg" rel="nofollow noreferrer">Example</a> 
   <a href="https://i.stack.imgur.com/jqJwg.jpg" rel="nofollow noreferrer">Example(w/o Arrows)</a></p>
  
  <p>The question is: How to detect these corners and crop everything outside them?</p>
  
  <p>Here is my current code:</p>
  
  <pre><code>for filenumber in range(2,7):
      img = cv2.imread('img' + str(filenumber) + '.tif')
  
      gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
      img2 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
      gray = cv2.bitwise_not(gray)
  
      img = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 25, 11)
      kernel = np.ones((2, 2), np.uint8)
      img = cv2.erode(img, kernel, iterations=3)
      thresh = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
      coords = np.column_stack(np.where(thresh &gt; 0))
      angle = cv2.minAreaRect(coords)[-1]
  
      if angle &lt; -45:
          angle = -(90 + angle)
      else:
          angle = -angle
      # rotate the image to deskew it
      (h, w) = img.shape[:500]
      center = (w // 400, h // 400)
      M = cv2.getRotationMatrix2D(center, angle, 1)
      rotated = cv2.warpAffine(img, M, (w, h),
          flags=cv2.INTER_CUBIC, borderMode=cv2.BORDER_REPLICATE)
      # draw the correction angle on the image so we can validate it
      cv2.putText(rotated, "Angle: {:.2f} degrees".format(angle),
          (100, 400), cv2.FONT_HERSHEY_SIMPLEX, 1.5, (0, 0, 255), 2)
  
      img = rotated
  
      th, threshed = cv2.threshold(img, 240, 255, cv2.THRESH_BINARY_INV)
      ## (2) Morph-op to remove noise
      kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11,11))
      morphed = cv2.morphologyEx(threshed, cv2.MORPH_CLOSE, kernel)
  
      ## (3) Find the max-area contour
      cnts = cv2.findContours(morphed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2]
      cnt = sorted(cnts, key=cv2.contourArea)[-1]
      ## (4) Crop and save it
      x,y,w,h = cv2.boundingRect(cnt)
      dst = img2[y:y+h, x:x+w]
      img = dst
      size_multiplier = szm = 1
      cv2.imwrite('img_' + str(filenumber) + '_Cropped' + '.jpg', img)
  
  #Configs for OCR segments
  for nnumb in range(2, 7):
      print('[INFO2]:   File=' + str(filenumber) + ';  nnumb=' + str(nnumb))
      if nnumb == 1:
          sub_image = img[130:130 + 90, 1220:1220 + 600]
          config = ('-l rus --oem 0 --psm 3 -c tessedit_char_whitelist="0123456789"')
      if nnumb == 2:
          sub_image = img[150:150 + 60, 1980:1980 + 460]
          config = ('-l rus --oem 1 --psm 3 -c tessedit_char_whitelist="0123456789"')
      if nnumb == 3:
          sub_image = img[230:230 + 70, 620:620 + 3000]
          config = ('-l rus --oem 0 --psm 3')
      if nnumb == 4:
          sub_image = img[410:410 + 70, 835:835 + 470]
          config = ('-l rus --oem 0 --psm 1 -c tessedit_char_whitelist="0123456789"')
      if nnumb == 5:
          sub_image = img[480:480 + 220, 610:610 + 1300]
          config = ('-l rus --oem 0 --psm 3')
      if nnumb == 6:
          sub_image = img[720:720 + 70, 110:110 + 500]
          config = ('-l rus --oem 0 --psm 3 -c tessedit_char_whitelist="0123456789"')
  </code></pre>
  
  <p>[<img src="https://i.stack.imgur.com/UsMCZ.jpg" alt="Result After first try"></p>
  
  <p>UPDATE: Final Code</p>
  
  <pre><code>def cornersandcrop(img):
      main_image = img
      main_imageF = main_image.copy()
      gray_image = main_image.copy()
      #Remove parts of image except corners
      gray_image[70:70 + 500, 70:70 + 500] = [255, 255, 255]
      gray_image[44:44 + 100, 1900:1900 + 550] = [255, 255, 255]
      gray_image[2270:2270 + 700, 45:45 + 200] = [255, 255, 255]
      gray_image[140:2880, 0:2500] = [255, 255, 255]
      gray_image[0:3000, 150:2350] = [255, 255, 255]
  
      gray_image = cv2.cvtColor(gray_image, cv2.COLOR_BGR2GRAY)
      gray_image = cv2.medianBlur(gray_image, 5)
      gray_image = cv2.adaptiveThreshold(gray_image, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY,11,20)
      kernel = np.ones((2, 2), np.uint8)
      gray_image = cv2.erode(gray_image, kernel, iterations=5)
      gray_image = cv2.dilate(gray_image, kernel, iterations=2)
      gray_image = cv2.morphologyEx(gray_image, cv2.MORPH_OPEN, np.ones((1, 1), np.uint8))
  
      template = cv2.imread('Templates\\Template_Corner_Top_Left.png', 0)
      template2 = cv2.imread('Templates\\Template_Corner_Top_Right.png', 0)
      template3 = cv2.imread('Templates\\Template_Corner_Bot_Right.png', 0)
      template4 = cv2.imread('Templates\\Template_Corner_Bot_Left.png', 0)
  
      width, height = template.shape[::-1] #get the width and height
      width2, height2 = template2.shape[::-1]
      width3, height3 = template3.shape[::-1]
      width4, height4 = template4.shape[::-1]
  
      match = cv2.matchTemplate(gray_image, template, cv2.TM_CCOEFF_NORMED)
      match2 = cv2.matchTemplate(gray_image, template2, cv2.TM_CCOEFF_NORMED)
      match3 = cv2.matchTemplate(gray_image, template3, cv2.TM_CCOEFF_NORMED)
      match4 = cv2.matchTemplate(gray_image, template4, cv2.TM_CCOEFF_NORMED)
  
      min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(match)
      top_Pos1 = max_loc
      Pos1 = (top_Pos1[0] + width-115, top_Pos1[1] + height-115)
      min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(match2)
      top_Pos2 = max_loc
      Pos2 = (top_Pos2[0] + width2-5, top_Pos2[1] + height2-115)
      min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(match3)
      top_Pos3 = max_loc
      Pos3 = (top_Pos3[0] + width3-5, top_Pos3[1] + height3-5)
      min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(match4)
      top_Pos4 = max_loc
      Pos4 = (top_Pos4[0] + width4-115, top_Pos4[1] + height4-5)
  
      src_pts = np.array([Pos1, Pos2, Pos3, Pos4], dtype=np.float32)
      dst_pts = np.array([[0, 0],   [3000, 0],  [3000, 2500], [0, 2500]], dtype=np.float32)
      M = cv2.getPerspectiveTransform(src_pts, dst_pts)
      warp = cv2.warpPerspective(main_imageF, M, (3000, 2500))
      warp = cv2.resize(warp, (int(2500), int(3000)),fx=1, fy=1, interpolation = cv2.INTER_CUBIC)
  return (warp)
  </code></pre>