title: Python OpenCV skew correction for OCR
body: <p>Currently, I am working on an OCR project where I need to read the text off of a label (see example images below). I am running into issues with the image skew and I need help fixing the image skew so the text is horizontal and not at an angle. Currently the process I am using attempts to score different angles from a given range (code included below), but this method is inconsistent and sometimes overcorrects an image skew or flat out fails to identify the skew and correct it. Just as a note, before the skew correction I am rotating all of the images by 270 degrees to get the text upright, then I am passing the image through the code below. The image passed through to the function is already a binary image.</p>
  <p>Code:</p>
  <pre><code>
  def findScore(img, angle):
      &quot;&quot;&quot;
      Generates a score for the binary image recieved dependent on the determined angle.\n
      Vars:\n
      - array &lt;- numpy array of the label\n
      - angle &lt;- predicted angle at which the image is rotated by\n
      Returns:\n
      - histogram of the image
      - score of potential angle
      &quot;&quot;&quot;
      data = inter.rotate(img, angle, reshape = False, order = 0)
      hist = np.sum(data, axis = 1)
      score = np.sum((hist[1:] - hist[:-1]) ** 2)
      return hist, score
  
  def skewCorrect(img):
      &quot;&quot;&quot;
      Takes in a nparray and determines the skew angle of the text, then corrects the skew and returns the corrected image.\n
      Vars:\n
      - img &lt;- numpy array of the label\n
      Returns:\n
      - Corrected image as a numpy array\n
      &quot;&quot;&quot;
      #Crops down the skewImg to determine the skew angle
      img = cv2.resize(img, (0, 0), fx = 0.75, fy = 0.75)
  
      delta = 1
      limit = 45
      angles = np.arange(-limit, limit+delta, delta)
      scores = []
      for angle in angles:
          hist, score = findScore(img, angle)
          scores.append(score)
      bestScore = max(scores)
      bestAngle = angles[scores.index(bestScore)]
      rotated = inter.rotate(img, bestAngle, reshape = False, order = 0)
      print(&quot;[INFO] angle: {:.3f}&quot;.format(bestAngle))
      #cv2.imshow(&quot;Original&quot;, img)
      #cv2.imshow(&quot;Rotated&quot;, rotated)
      #cv2.waitKey(0)
      
      #Return img
      return rotated
  </code></pre>
  <p>Example images of the label before correction and after</p>
  <p>Before correction <code>-&gt;</code> After correction</p>
  <img src="https://imgur.com/CO32WLn.png" width="300">
  <img src="https://imgur.com/XRaJ9Bz.png" width="300">
  <p>If anyone can help me figure this problem out, it would be of much help.</p>