pythonopencvsignal-processingtechnical-indicator

Hough lines missing some lines


I'm trying to detect lines in an irregular image using a relatively low threshold of 5. The result I get is the following:

enter image description here

where red lines are the computed lines. However, I was expecting the yellow lines to satisfy the parameters as well. Does anyone know why the yellow lines aren't detected? Here's my code:

# img
rho = 1  # distance resolution in pixels of the Hough grid
theta = np.pi / 180  # angular resolution in radians of the Hough grid
threshold = 5  # minimum number of votes (intersections in Hough grid cell)
min_line_length = 200  # minimum number of pixels making up a line
max_line_gap = 500  # maximum gap in pixels between connectable line segments

low_threshold = 50
high_threshold = 150

edge_image = img.copy()
edge_image = cv2.GaussianBlur(edge_image, (3, 3), 1)
edges = cv2.Canny(edge_image, low_threshold, high_threshold)

line_image = np.copy(edges)  # creating a blank to draw lines on
line_image = cv2.cvtColor(line_image, cv2.COLOR_GRAY2BGR)

lines = cv2.HoughLinesP(img, rho, theta, threshold, np.array([]),
                    min_line_length, max_line_gap)

for line in lines:
    for x1,y1,x2,y2 in line:
        cv2.line(line_image,(x1,y1),(x2,y2),(0,0,255),1)

Solution

  • There are few issues with the posted solution:


    Code sample:

    import cv2
    import numpy as np
    
    img = cv2.imread('input_image_with_lines.png')  # Read image as BGR
    
    # Apply threshold to each color channel for converting all the non-black pixels to white (needed to the usage of automatic threshold instead of manual threshold).
    b_thres = cv2.threshold(img[:, :, 0], 0, 255, cv2.THRESH_OTSU)[1]  # Apply automatic threshold to the blue channel
    g_thres = cv2.threshold(img[:, :, 1], 0, 255, cv2.THRESH_OTSU)[1]  # Apply automatic threshold to the green channel
    r_thres = cv2.threshold(img[:, :, 2], 0, 255, cv2.THRESH_OTSU)[1]  # Apply automatic threshold to the red channel
    thres_image = b_thres | g_thres | r_thres  # thres_image is combined threshold images
    
    #dilated_thres_image = cv2.dilate(thres_image, np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]], np.uint8))
    dilated_thres_image = cv2.dilate(thres_image, np.ones((2, 2), np.uint8))  # Dilate thres_image with very small kernel - makes the lines thinker. 
    
    # img
    rho = 0.5  #1 distance resolution in pixels of the Hough grid
    theta = np.pi / 180  # angular resolution in radians of the Hough grid
    threshold = 5  # minimum number of votes (intersections in Hough grid cell)
    min_line_length = 50 #200  # minimum number of pixels making up a line
    max_line_gap = 2 #500  # maximum gap in pixels between connectable line segments
    
    #low_threshold = 50
    #high_threshold = 150
    
    #edge_image = img.copy()
    #edge_image = cv2.GaussianBlur(edge_image, (3, 3), 1)
    #edges = cv2.Canny(edge_image, low_threshold, high_threshold)
    
    #lines = cv2.HoughLinesP(img, rho, theta, threshold, np.array([]),
    #                    min_line_length, max_line_gap)
    
    lines = cv2.HoughLinesP(dilated_thres_image, rho, theta, threshold, None, min_line_length, max_line_gap)
    
    line_image = cv2.cvtColor(dilated_thres_image, cv2.COLOR_GRAY2BGR) # creating a blank to draw lines on
    
    for line in lines:
        for x1,y1,x2,y2 in line:
            #cv2.line(line_image,(x1,y1),(x2,y2),(0,0,255),1)
            cv2.line(line_image, (x1,y1), (x2,y2), (0,255,0), 1)
    
    
    # Display images for testing
    cv2.imshow('img', img)
    cv2.imshow('thres_image', thres_image)
    cv2.imshow('dilated_thres_image', dilated_thres_image)
    cv2.imshow('line_image', line_image)
    cv2.waitKey()
    cv2.destroyAllWindows()
    

    Output:
    enter image description here

    I realize that the result is not perfect, but we have to consider that Hough-Lines algorithm has its limitations...