python-3.xopencvimage-morphology

cv2.MORPH_CLOSE joining letters together



I'm using Opencv to do some morphological operations on an image: input but it joins some of the letters together creating problems when I detect it's contours. For example:

joined letters

Is there some tweaking I can do wih my code to fix this or will I have to do this a different way?(but it has to be a closing algorithm or function because it is pretty helpful in preprocessing).

My code I am using is as below:

kernel = np.ones((5,5),np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
closing = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, kernel)

Solution

  • Here is workable solution:

      import numpy as np
      import cv2
      from matplotlib import pyplot as plt
    
      I = cv2.imread('/home/smile/Downloads/words.jpg',cv2.IMREAD_GRAYSCALE)
    
      _,It = cv2.threshold(I,0.,255,cv2.THRESH_OTSU)
      It = cv2.bitwise_not(It)
      _,labels = cv2.connectedComponents(I)
    
      result = np.zeros((I.shape[0],I.shape[1],3),np.uint8)
    
      for i in range(labels.min(),labels.max()+1):
         mask = cv2.compare(labels,i,cv2.CMP_EQ)
    
         _,ctrs,_ = cv2.findContours(mask,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
    
         result = cv2.drawContours(result,ctrs,-1,(0xFF,0,0))
    
      plt.figure()
      plt.imshow(result)    
      plt.axis('off')
    

    During the two first steps the image is binarize and reverse in order to make the letters appear has white over black.

    _,It = cv2.threshold(I,0.,255,cv2.THRESH_OTSU)
    It = cv2.bitwise_not(It)
    

    bin

    Then during the next step each letter become a labelized region.

    _,labels = cv2.connectedComponents(I)
    

    labels

    The final step consist for each label value to find the area in the image that correspond to it, process the external contour of that area and "draw" it in the output image.

    result = np.zeros((I.shape[0],I.shape[1],3),np.uint8)
    
    for i in range(labels.min(),labels.max()+1):
       mask = cv2.compare(labels,i,cv2.CMP_EQ)
    
       _,ctrs,_ = cv2.findContours(mask,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
    
       result = cv2.drawContours(result,ctrs,-1,(0xFF,0,0)
    

    Hope it helps.