title: OpenCV digits merging into surrounding boxes
body: <p>I've got a bunch of dates i'm trying to OCR using tesseract.
  However, a lot of the digits in the dates merge with the lines in the date boxes as so:</p>
  
  <hr>
  
  <p><img src="https://i.stack.imgur.com/7Ac56.jpg" alt="Digits intersecting boxes">
  <img src="https://i.stack.imgur.com/nYuPm.jpg" alt="Digits intersecting boxes">
  <img src="https://i.stack.imgur.com/RyXka.jpg" alt="Digits intersecting boxes">
  <img src="https://i.stack.imgur.com/AZJ7n.jpg" alt="Digits intersecting boxes"></p>
  
  <hr>
  
  <p>Also, here's a good image that i can tesseract well with:
  <img src="https://i.stack.imgur.com/IFbGO.jpg" alt="Good Date Image"></p>
  
  <hr>
  
  <p>And here's my code:</p>
  
  <pre><code>import os
  import cv2
  from matplotlib import pyplot as plt
  import subprocess
  import numpy as np
  from PIL import Image
  
  def show(img):
      plt.figure(figsize=(20,20))
      plt.imshow(img,cmap='gray')
      plt.show()
  
  def sort_contours(cnts, method="left-to-right"):
      # initialize the reverse flag and sort index
      reverse = False
      i = 0
  
      # handle if we need to sort in reverse
      if method == "right-to-left" or method == "bottom-to-top":
          reverse = True
  
      # handle if we are sorting against the y-coordinate rather than
      # the x-coordinate of the bounding box
      if method == "top-to-bottom" or method == "bottom-to-top":
          i = 1
  
      # construct the list of bounding boxes and sort them from top to
      # bottom
      boundingBoxes = [cv2.boundingRect(c) for c in cnts]
  
      cnts, boundingBoxes = zip(*sorted(zip(cnts, boundingBoxes),
          key=lambda b:b[1][i], reverse=reverse))
  
      # return the list of sorted contours and bounding boxes
      return cnts, boundingBoxes
  
  
  def tesseract_it(contours,main_img, label,delete_last_contour=False):
      min_limit, max_limit = (1300,1700)
      idx =0 
      roi_list = []
      slist= set()
      for cnt in contours:
          idx += 1
          x,y,w,h = cv2.boundingRect(cnt)
          if label=='boxes':
              roi=main_img[y+2:y+h-2,x+2:x+w-2]
          else:
              roi=main_img[y:y+h,x:x+w]
  
          if w*h &gt; min_limit and w*h &lt; max_limit and w&gt;10 and w&lt; 50 and h&gt;10 and h&lt;50:
              if (x,y,w,h) not in slist: # Stops from identifying repeted contours
  
                  roi = cv2.resize(roi,dsize=(45,45),fx=0 ,fy=0, interpolation = cv2.INTER_AREA)
                  roi_list.append(roi)
                  slist.add((x,y,w,h))
  
      if not delete_last_contour:
          vis = np.concatenate((roi_list),1)
      else:
          roi_list.pop(-1)
          vis = np.concatenate((roi_list),1)
  
      show(vis)
  
      # Tesseract the final image here
      # ...
  
  
  image = 'bad_digit/1.jpg'
  # image = 'bad_digit/good.jpg'
  specimen_orig = cv2.imread(image,0)
  
  
  specimen = cv2.fastNlMeansDenoising(specimen_orig)
  #     show(specimen)
  kernel = np.ones((3,3), np.uint8)
  
  # Now we erode
  specimen = cv2.erode(specimen, kernel, iterations = 1)
  #     show(specimen)
  _, specimen = cv2.threshold(specimen, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
  #     show(specimen)
  specimen_canny = cv2.Canny(specimen, 0, 0)
  #     show(specimen_canny)
  
  specimen_blank_image = np.zeros((specimen.shape[0], specimen.shape[1], 3))
  _,specimen_contours, retr = cv2.findContours(specimen_canny.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE )
  # print(len(specimen_contours))
  cv2.drawContours(specimen_blank_image, specimen_contours, -1, 100, 2)
  #     show(specimen_blank_image)
  specimen_blank_image = np.zeros((specimen.shape[0], specimen.shape[1], 3))
  
  specimen_sorted_contours, specimen_bounding_box = sort_contours(specimen_contours)
  
  output_string = tesseract_it(specimen_sorted_contours,specimen_orig,label='boxes',)
  # return output_string
  </code></pre>
  
  <hr>
  
  <p>The output from the good image attached is so:
  <img src="https://i.stack.imgur.com/qHPSd.png" alt="Good output"></p>
  
  <hr>
  
  <p>Tesseracting this image does give me accurate results.</p>
  
  <p>However, for the ones where the lines are merging into the digits, my output looks like this:
  <img src="https://i.stack.imgur.com/8aY60.png" alt="bad1">
  <img src="https://i.stack.imgur.com/2GE45.png" alt="bad2">
  <img src="https://i.stack.imgur.com/wiAXc.png" alt="bad3">
  <img src="https://i.stack.imgur.com/MEgxY.png" alt="bad4"></p>
  
  <p>These do not work well with Tesseract at all.
  I was wondering if there was a way to remove the lines and keep only the digits.</p>
  
  <p>I have tried the following as well:
  <a href="https://docs.opencv.org/3.2.0/d1/dee/tutorial_moprh_lines_detection.html" rel="noreferrer">https://docs.opencv.org/3.2.0/d1/dee/tutorial_moprh_lines_detection.html</a></p>
  
  <p>Which doesn't really seem to do great on the images i've attached.</p>
  
  <p>I've also tried to use imagemagick:</p>
  
  <pre><code>convert original.jpg \
  \( -clone 0 -threshold 50% -negate -statistic median 200x1 \)  \
  -compose lighten -composite                                    \
  \( -clone 0 -threshold 50% -negate -statistic median 1x200 \)  \
  -composite output.jpg
  </code></pre>
  
  <p>Its results are fair, but the line removed somewhat cuts through the digits as following:</p>
  
  <p><img src="https://i.stack.imgur.com/0fWQQ.jpg" alt="imagemagick1">
  <img src="https://i.stack.imgur.com/WrNK8.jpg" alt="imagemagick2">
  <img src="https://i.stack.imgur.com/TXdKD.jpg" alt="imagemagick3">
  <img src="https://i.stack.imgur.com/YHnWM.jpg" alt="imagemagick4"></p>
  
  <p>Is there a better way i can approach this problem? My final goal is to tesseract the digits, so the final image does need to be quite clear.</p>