Search code examples
pythonopencvimage-processingcomputer-visionedge-detection

Excluding Empty Edges When Morph Closing Lines In An Image


How to connect disjoint vertical lines in an image without expanding them over the outer margin area?

Input image (simplified example) :

Input Image Example

Using Morph Close operation :

inputImg = cv2.imread(imgPath)
grayInput = cv2.cvtColor(inputImg, cv2.COLOR_BGR2GRAY)
thre = cv2.inRange(grayInput, 0, 155)

closed = cv2.morphologyEx(thre, cv2.MORPH_CLOSE, np.ones((500,1), np.uint8))

Current output :

Current output

Desired output :

Desired output

P.S. I could just add margin that is greater than the closing kernel but this would be memory inefficient due to the large size of the production images. Production images have important amount of lines with random gaps as well.


Solution

  • Binarize your image, find the columns that contain white pixels, then connect the lines between the lowest and highest white pixels in each column.

    The below code will accomplish this. I explained it with comments.

    import cv2
    import numpy as np
    
    img = cv2.imread("xoxql.png") # Load the image
    img = (img < 255).all(axis=2) # Binarize the image
    rows, cols = img.nonzero() # Get all nonzero indices
    unique_cols = np.unique(cols) # Select columns that contain nonzeros
    for col_index in unique_cols: # Loop through the columns
        start = rows[col_index == cols].min() # Select the lowest nonzero row index
        end = rows[col_index == cols].max() # Select the highest nonzero row index
        img[start:end, col_index] = True # Set all "pixels" to True between the lowest and highest row indices
    img = img * np.uint8(255) # Multiply by 255 to convert the matrix back to an image
    cv2.imwrite("result.png", img) # Save the image
    

    enter image description here

    The lines on the right side of your image are not exactly lined up, which will leave some gaps on the edges.