Lane Line Detection

Lane Line Detection

Lane Line Detection

A guide to creating a simple pipeline to detect lane lines in a video feed using basic Computer Vision techniques.

Libraries and Tools Used

This project uses key Python libraries for image and video processing:

  • cv2 (OpenCV): For all image manipulation, including color conversion, edge detection, and drawing.
  • numpy: Essential for numerical operations on image arrays.
  • matplotlib: Useful for visualizing intermediate steps if needed.

1. Preprocessing the Image

  • What the code does: It takes a video frame, converts it to grayscale, applies a Gaussian blur to reduce noise, and then uses the Canny edge detection algorithm to find all the edges in the image.
  • Behind the scenes: Grayscale simplifies the image data. Blurring helps the Canny algorithm by smoothing out noise. Canny edge detection is a multi-stage process that identifies sharp changes in intensity, which correspond to edges like lane lines.
  • Abstraction: OpenCV's functions (`cvtColor`, `GaussianBlur`, `Canny`) abstract the complex mathematical operations involved in these preprocessing steps, allowing us to focus on the pipeline logic.
import cv2
import numpy as np

def process_frame(image):
    # Convert to grayscale
    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    
    # Apply Gaussian blur to reduce noise
    blurred_image = cv2.GaussianBlur(gray_image, (5, 5), 0)
    
    # Use Canny edge detection
    canny_edges = cv2.Canny(blurred_image, 50, 150)
    
    return canny_edges

# This part would be inside a video processing loop
# For demonstration, we'll assume 'frame' is a single image
# canny_output = process_frame(frame)

2. Defining the Region of Interest (ROI) and Hough Transform

  • What the code does: It creates a triangular mask to focus only on the road area in the video frame. Then, it applies the Hough Transform on this masked region to detect lines.
  • Behind the scenes: The Hough Transform is an algorithm that finds lines by mapping points in the image to potential line equations. By masking the image, we drastically reduce the processing area and avoid detecting lines that aren't part of the road.
  • Abstraction: `cv2.fillPoly` and `cv2.HoughLinesP` abstract the geometric masking and the complex voting process of the Hough Transform, respectively.
def region_of_interest(image):
    height, width = image.shape
    # Define a triangular region of interest
    polygons = np.array([
        [(200, height), (1100, height), (550, 250)]
    ])
    mask = np.zeros_like(image)
    cv2.fillPoly(mask, polygons, 255)
    masked_image = cv2.bitwise_and(image, mask)
    return masked_image

def hough_lines(image):
    # Use the Probabilistic Hough Transform
    # Arguments: rho, theta, threshold, minLineLength, maxLineGap
    lines = cv2.HoughLinesP(image, 2, np.pi / 180, 100, np.array([]), minLineLength=40, maxLineGap=5)
    return lines

# Assuming canny_output from step 1
# roi_output = region_of_interest(canny_output)
# lines = hough_lines(roi_output)

3. Drawing and Averaging the Lines

  • What the code does: It defines a function to draw the detected lines on a blank image and then another function to average multiple short lines into a single, longer line for the left and right lanes.
  • Behind the scenes: The Hough Transform can detect many short lines for each lane. We use linear regression to average these lines into two solid lines, one for the left lane and one for the right.
  • Abstraction: The custom `average_slope_intercept` function handles the complex logic of separating and averaging the lines based on their slope, a critical step for a clean result.
def draw_lines(image, lines, color=(255, 0, 0), thickness=10):
    line_image = np.zeros_like(image)
    if lines is not None:
        for line in lines:
            x1, y1, x2, y2 = line.reshape(4)
            cv2.line(line_image, (x1, y1), (x2, y2), color, thickness)
    return line_image

def average_slope_intercept(image, lines):
    left_fit = []
    right_fit = []
    if lines is not None:
        for line in lines:
            x1, y1, x2, y2 = line.reshape(4)
            parameters = np.polyfit((x1, x2), (y1, y2), 1)
            slope = parameters[0]
            intercept = parameters[1]
            if slope < 0: # Left lane lines have negative slope
                left_fit.append((slope, intercept))
            else: # Right lane lines have positive slope
                right_fit.append((slope, intercept))
    # ... logic to average and draw lines ...
    return left_fit, right_fit

# Assuming lines from step 2
# line_image = draw_lines(np.zeros_like(frame), lines)
# final_image = cv2.addWeighted(frame, 0.8, line_image, 1, 1)

Comments

Popular posts from this blog

Simple Augmented Reality (AR) App

Image Captioning

Pose Estimation