title: Merging contour areas in close proximity
body: <p>I'm working on parsing coupon codes from receipts, and unfortunately, the letters are not solid lines. They composed of small individual dots. I  managed to do some image manipulation and find the dots, but this is where I'm stuck. Is there a way to connect or merge the dots that are close to each other? Is there a simple solution to this?</p>
  
  <p>Here is the original image and also images after finding the dots.</p>
  
  <p><a href="https://i.stack.imgur.com/6XpEl.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/6XpEl.jpg" alt="enter image description here"></a>
  <a href="https://i.stack.imgur.com/tXxZ6.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/tXxZ6.png" alt="enter image description here"></a>
  <a href="https://i.stack.imgur.com/xlVXy.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/xlVXy.jpg" alt="enter image description here"></a></p>
  
  <p>Here is the code I came up with.</p>
  
  <pre><code>import cv2
  import numpy as np
  
  
  def load_local_image(image):
      c_img = cv2.imread(image, cv2.IMREAD_COLOR)
      g_img = cv2.imread(image, cv2.IMREAD_GRAYSCALE)
      return (cv2.resize(c_img, (800, 800)), cv2.resize(g_img, (800, 800)))
  
  
  def find_letters(binary_image, rgb_image, settings):
      contours, hierarchy = cv2.findContours(binary_image.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
      letters = []
  
      for contour in contours:
          if cv2.contourArea(contour) &gt; settings['contour_area_threshold']:
              # four points of bounding box for each character
              x, y, w, h = cv2.boundingRect(contour)
              # draw the bounding rectangle from points above
              cv2.rectangle(rgb_image, (x, y), (x + w, y + h), settings['outline_color'], settings['outline_thickness'])
              # print 'x:{}, y:{}, width:{}, height:{}'.format(x, y, w, h)
              letters.append((x, y, w, h))
      return sorted(letters, key=lambda x: x[0])
  
  
  def alter_image(img):
      blur = cv2.GaussianBlur(g, (3, 3), 0)
      ret, thresh1 = cv2.threshold(blur, 50, 255, cv2.THRESH_BINARY)
      bitwise = cv2.bitwise_not(thresh1)
      erosion = cv2.erode(bitwise, np.ones((1, 1) ,np.uint8), iterations=1)
      dilation = cv2.dilate(erosion, np.ones((3, 3) ,np.uint8), iterations=1)
      return dilation
  
  
  c, g = load_local_image('img.jpg')
  altered_img = alter_image(g)
  
  contour_settings = {
      'contour_area_threshold': 1,
      'outline_thickness': 1,
      'outline_color': (66, 116, 244)
  }
  letters_crop = find_letters(altered_img, c, contour_settings)
  
  cv2.imshow('color', c)
  cv2.imshow('gray', altered_img)
  cv2.waitKey()
  cv2.destroyAllWindows()
  </code></pre>