Project

Lane Detection using Hough Transform

Objective

1. Detect lanes using Hough Transform Method.

Steps in lane Detection

1. Detect Edges using Canny Edge Detection Method.

2. Capture the Region of Interest in Image.

3. Detect lines using Hough Transform.

4. Calculate the actual left and right lanes from all lines.

6. Find the coordinates of the lines.

7. Display the lines on the Image.

challenges may Face in Line Detection,

The present solution we walk through here, is good for Normal road conditions and small curves.

First Frame of the Video

code

def canny(image):

    # convert 3 channel RGB Image to single channel gray scale [0-255]
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # Smoothening the Image, to reduce the Local Noise, robust for edge detection
    blur = cv2.GaussianBlur(gray, (5, 5), 0)

    # Detect the Edges using opencv canny Edge Method.
    return cv2.Canny(blur, 50, 150)

step1:

1. Convert RGB Image(3channel) into grayScale (single channel Image), reduces computational cost to detect the Edges.

2. Gaussian Blurring, helps to reduce the local Noises in the Image, and can accurately detect the correct Edges.

3. Edge Detection using canny Method. (Robust Method to detect edges).

Result of Step 1:

code

def capture_region_of_interest(image):
    height = image.shape[0]
    width = image.shape[1]

    # Creating an Black Image for Mask
    black = np.zeros_like(image) # black image

    # Polygon coordinates
    poly_coords = np.array([(0, height), (0, round(height*0.80)), (round(width/2), round(height/2)), (width, height)]) # CV Indexing.

    # Filling the Polygon with 255 Pixel Intensity.
    mask = cv2.fillPoly(black, [poly_coords], 255)

    # Bitwise and operation b/w Image and the Mask, 
    return (cv2.bitwise_and(image, mask), cv2.addWeighted(image, 0.8, mask, 0.2, 0))

step2:

1. Create an Black Image with the size of the Input Image from the parameter, to create a Mask and Extract ROI(Region of Interest) from the Image.

2. Calcuate the Coordinates of the polygon as a Numpy Array.

3. Fill the Polygon with 255 pixel Intensity, using cv2.fillPoly inbuilt Function.

4. Bitwise_and(&) Operation between the Edge Image and Mask.

Result of Step 2:

code

Hough_lines = cv2.HoughLinesP(roi, 2, np.pi/180, 100, np.array([]), minLineLength=20, maxLineGap=5)

step3:

1. Hough Lines re used to detect the Lines in the Image, cv2.HoughLinesP gives coordinates of the End points of the lines detected.

For code Explanation :- https://github.com/alyssaq/hough_transform

Result of Step 3:

code

cv2.HoughLinesP(roi_img, 1, np.pi/180, 50, np.array([]), minLineLength=0, maxLineGap=1000)

step4:

1. After lines detected using HoughTransform, Filter out the lines, (remove the Noise lines)

2. np.polyfit() gives the parameter values based on the data and degree of the expression specified.

3. Divide the lines into left and right based on the slope value.

  • If slope < -0.1 :- Left lines.
  • If slope > 0 .2 :- Right lines.
  • Here -0.1, 0.2 cconsidered to remove the effect of the Horizontal lines.
  • Think in the perspective of the Computer Vision co-ordinate system.

4. 2 Scenarios

  • At the turning location, both sides may contain the same sign of the slopes.
  • Noise lines between the left and right lanes.

5. calculate_threshold() calculate the threshold of cosine distances based on the percentile values provided.

6. cosines distances, provides the distance between the lines in the range of [0, 1] irrespective if the distance values.

Result of Step 4:

code

def average_slope_intercept(image, lines):
    """
    0. Iterate over all the lines.q
    1. polyfit - calculate slope and intercept of the lines. (slope, intercept) 
    2. slope < 0 :- Left lane, 
       slope > 0 :- Right lane.
    3. Divide the lines into seperate lists.q
    """
    left_lines, right_lines= [], []
    left_cords, right_cords = [], []

    for line in lines:
        x1, y1, x2, y2 = line.reshape(4) # From Hough Lines
        slope, intercept = np.polyfit((x1, x2), (y1, y2), 1)

        if slope < -0.1:
            left_lines.append([slope, intercept])
            left_cords.append(calculate_coordinates(image, (slope, intercept)))

        elif (slope > 0.2):   
            right_lines.append([slope, intercept])
            right_cords.append(calculate_coordinates(image, (slope, intercept)))
.
    if len(left_cords)==0 or len(right_cords)==0:
        if len(left_cords)==0:
            lines = right_cords
        else:
            lines = left_cords

        if len(lines)<=2:
            return np.array(lines)
        
        threshold = calculate_threshold(lines, lines, 80)
        final_left_lines, final_right_lines = filter_noise_lines(lines, lines, threshold)

    else:
        threshold = calculate_threshold(left_cords, right_cords, 85)
        final_left_lines, final_right_lines = filter_noise_lines(left_cords, right_cords, threshold)


    left_line = np.average(np.array(final_left_lines), axis=0)
    right_line = np.average(np.array(final_right_lines), axis=0)
    return np.array([left_line, right_line]) 

step4 helper functions

# Calculate the threshold value, based on the coordinate values.
def calculate_threshold(left_cords, right_cords, percen):
    """
    @param left_cords array of left lines Coordinates
    @param right_cords array of right lines Coordinates
    @param percen percentile value
    """
    cosine_dist = []
    for left_line in left_cords:
        for right_line in right_cords :
             cosine_dist.append(cosine(left_line, right_line))
    cosine_dist = [item for item in cosine_dist if not math.isnan(item)]
    threshold = np.percentile(cosine_dist, percen)
    return threshold

# Filter the Noise lines from all the lines.
def filter_noise_lines(left_cords, right_cords,threshold):
    """
    @param left_cords array of left lines Coordinates
    @param right_cords array of right lines Coordinates
    @param threshold constraint value of the cosine distance
    """
    final_left_lines = []
    final_right_lines = []

    for left in left_cords: 
        for right in right_cords:
            dist = cosine(left, right)

            if dist > threshold:
                if list(left) not in final_left_lines:
                    final_left_lines.append(list(left))
                if list(right) not in final_right_lines:
                    final_right_lines.append(list(right))
    return [final_left_lines, final_right_lines]

step5:

1. Calulate the Coordinates of the lines with the help of line parameters, here chosen y1 as height of the Image(Bottom), y2 as `(3/5)^(th` of the Image Height.

2. Draw line on the Image using cv2.line

code

def calculate_coordinates(image, params): 
    # Calculating the final line co-ordinates.
    slope, intercept = params
    y1 = image.shape[0]
    x1 = int((y1 - intercept)/slope)
    y2 = image.shape[0]*(3/5)
    x2 = int((y2 - intercept)/slope)
    return np.array([x1, y1, x2, y2], dtype=np.uint64)

def disply_lines(image, lines):
    if lines:
        for line in lines:
            x1, y1, x2, y2 = line
            cv2.line(image, (x1, y1), (x2, y2), (0, 255, 0), 2)
        return image
    else:
        print("No lines Found")

Result of Step 5:

Driver code

def detect_lane(image):

    canny_img = canny(image)
    roi_img = capture_region_of_interest(canny_img)
    hough_lines  = cv2.HoughLinesP(roi_img, 1, np.pi/180, 50, np.array([]), minLineLength=0, maxLineGap=1000)
    lines = average_slope_intercept(roi_img, hough_lines)
    threshold = spatial.distance.cosine(lines[0], lines[1])
    lane_marked = display_lines(image, lines)
    return threshold, lane_marked


while(video.isOpened()):
    ret, frame = video.read()
    if ret == True:
        threshold, final_image = detect_lane(frame)  
        if 0.2<=threshold<=0.3:
            cv2.imshow("output",final_image)
            result.write(final_image)
            k = cv2.waitKey(20)
            if k ==113:
                break
        else:
            continue
    else:
        break

output Video

Conclusion

1. Detected the lines with the help of HoughLines.

2. For advance lane detection, can apply the methods like perspective transform, camera calibration, good color Transformation (like HSL) ...

Your portfolio, next

Ship work like this
in your own course.

Talk to a career counsellor

Free 20-minute call. We'll map the right course to where you want to work.

By submitting you agree to our Terms and Privacy Policy.