pythonopencvimage-processingcomputer-visionstraight-line-detection

How to remove all the detected lines from the original image using Python?


I am trying to remove all the lines present in the image. I am able to detect the lines but when I am trying to remove the lines, I am still getting few small lines in the final image. I have used cv2.getStructuringElement to get both the horizontal and vertical lines. In some cases, the final image is getting completely distorted and I am not able to move forward

The image is taken from google

Original Image Lines detected

    res = verticle_lines_img + horizontal_lines_img 
    res = cv2.bitwise_not(res)
    fin=cv2.bitwise_or(img_bin, res,mask =cv2.bitwise_not(res))
    fin= cv2.bitwise_not(fin)
    exp =255-res
    final = cv2.bitwise_and(exp,img_bin)
    final = cv2.bitwise_not(final)
    exp = ~exp
    finalised = cv2.bitwise_and(img_bin,final)
    finalised = cv2.bitwise_not(finalised)

Please help! Thanks


Solution

  • Here's an approach


    After converting to grayscale, we Otsu's threshold to get a binary image

    image = cv2.imread('1.jpg')
    gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
    thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
    

    From here we construct a special horizontal kernel to detect horizontal lines. Once the lines are detected, we fill in the lines to effectively remove the line

    # Remove horizontal
    horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (10,1))
    detected_lines = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2)
    cnts = cv2.findContours(detected_lines, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]
    for c in cnts:
        cv2.drawContours(image, [c], -1, (255,255,255), 2)
    

    Similarly, to remove vertical lines, we construct a special vertical kernel

    # Remove vertical
    vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,10))
    detected_lines = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, vertical_kernel, iterations=2)
    cnts = cv2.findContours(detected_lines, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]
    for c in cnts:
        cv2.drawContours(image, [c], -1, (255,255,255), 2)
    

    Here's the detected lines in green

    Result

    You can fine tune the results by adjusting the kernel size. For instance, changing (10,1) to say (15,1) will tighten the line detection while lowering it to (5,1) will loosen the detection

    Full Code

    import cv2
    
    image = cv2.imread('1.jpg')
    gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
    thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
    
    # Remove horizontal
    horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (10,1))
    detected_lines = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2)
    cnts = cv2.findContours(detected_lines, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]
    for c in cnts:
        cv2.drawContours(image, [c], -1, (255,255,255), 2)
    
    # Remove vertical
    vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,10))
    detected_lines = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, vertical_kernel, iterations=2)
    cnts = cv2.findContours(detected_lines, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]
    for c in cnts:
        cv2.drawContours(image, [c], -1, (255,255,255), 2)
    
    cv2.imshow('thresh', thresh)
    cv2.imshow('image', image)
    cv2.waitKey()