Skip to main content

Lane Detection Using Image Processing || Lane Detection with Python OpenCV - Creation Code



Introduction:

Autonomous Driving Car is one of the most disruptive innovations in AI. Fuelled by Deep Learning algorithms, they are continuously driving our society forward and creating new opportunities in the mobility sector. An autonomous car can go anywhere a traditional car can go and does everything that an experienced human driver does. But it's very essential to train it properly. One of the many steps involved during the training of an autonomous driving car is lane detection, which is the preliminary step. Today, we are going to learn how to perform lane detection using videos.


You can find the necessary files here

Code:

import cv2
import numpy as np
 
# Canny edge detection
# It's easier to find edges between pixels if
# we're able to convert the entire image into gray.
def canny(img):
    # Turn the images Gray
    # Processing a single channel instead of
    # three (R/G/B) color image, is a lot more faster.
    gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
    # Smooth and reduce noise (Gaussian Filter)
    # To understand the concept of a Gaussian filter
    # recall that an image is stored as a collection
    # of discrete pixels. Each of the pixels for a
    # grayscale image is represented by a single number
    # that discribes the brightness of the pixel. For the
    # sake of example, how do we smooth in the following
    # image? We modify the value of a pixel with the average
    # value of the pixel intensities around it. Averaging out
    # out the pixels in the image to reduce noise will be
    # done with the kernel (5x5). Each element within the
    # kernel contain gaussian values.
    kernel = 5
    blur = cv2.GaussianBlur(gray,(kernel, kernel),0)
    # Gradient Intensity
    # Identifying edges by seeing a sharp change in color
    # between adjacent pixels in the image. The change in
    # brightness over a series of pixels is the gradient.
    # A strong gradient indicates a steep change wheras a
    # small gradient is a shallow change. We first establish
    # that an image as it's composed
    # 50 lowest thershold
    # 150 highest thereshold
    canny = cv2.Canny(gray, 50, 150)
    return canny

# We need to mask the image to
# a region where we need to detect
def region_of_interest(canny):
    # y-axis
    # Bottom left corner of an image
    height = canny.shape[0]
    # x-axis
    # Bottom left corner of an image
    width = canny.shape[1]
    # Creates an array, size equal to
    # the image, of zero to make every
    # thing black outside the region
    # of interest.
    mask = np.zeros_like(canny)
    # Region of
    # interest boundaries
    triangle = np.array([[
    (200, height),
    (550, 250),
    (1100, height),]], np.int32)
    # Fill the mask with the polygon
    # (triangle) shape
    cv2.fillPoly(mask, triangle, 255)
    # Do a bitwise "AND" logic comparison
    # with white and black pixels beteen the
    # masked image (black background with white
    # triangle covering the lane) against the
    # canny image (original image with edge
    # detection).
    masked_image = cv2.bitwise_and(canny, mask)
    return masked_image

# (1) It's important to design a houghLines transform to
# design the lines for our given traffic lane.
# instead of using the cartesian coordinates (y and m):
# y = mx + b
# (2) We will be using the polar coordinates (row [p] and
# theta): p = xcos(theta) + ysin(theta)
# (3) Arguments:
# (3a) Image, number of pixels per bin, degree,
# radians (np.pi/180 == 1 radians)
# (3b) the minimum number of votes (intersection) in
# hough-space for a bin needs to be 100 for it to be
# accepted as a relevent line in describing our data
# (3c) placeholder array to pass in content
# (3d) length of a line in pixels we will accept into
# the output (minLineLength)
# (3e) maximum distance in pixels between segmented
# lines (maxLineGap) to be connected into one line.
def houghLines(cropped_canny):
    return cv2.HoughLinesP(cropped_canny, 2, np.pi/180, 100,
        np.array([]), minLineLength=40, maxLineGap=5)

# (1) Taking the sum of our color image
# with our line image (black-blue lines)
# (2) Arguments:
# (2a) Lane image
# (2b) Taking the weighted sum between the arrays
# between the two images provided in this function.
# Will give a value of 0.8 that multiple each element
# within the first image provided in the input function.
# It will decrease the pixel intensity.
# (2c) Taking the weighted sum between the arrays
# between the two images provided in this function.
# Will give a value of 1 that multiple each element
# within the second image provided in the input function.
# It will increase the pixel intensity compared to the first
# image. The lines will be more revealing than the frame.
# (2d) Gamma argument where we can choose some values
# that will add to our some. We put a scalue value of 1 which
# won't put sabstantial difference.
def addWeighted(frame, line_image):
    return cv2.addWeighted(frame, 0.8, line_image, 1, 1)
 
# This will return a black image
# except within the region of,
# interest will have blue lines
# displayed within the traffic lane.
def display_lines(img,lines):
    # Start with a black image
    # with the same dimensions as the
    # original picture of the road
    line_image = np.zeros_like(img)
    if lines is not None:
        # iterate existing
        # line points given
        # from hough lines
        for line in lines:
            for x1, y1, x2, y2 in line:
                # (255,0,0): Blue color
                # Line thickness
                cv2.line(line_image,(x1,y1),(x2,y2),(255,0,0),10)
    return line_image

#
def make_points(image, line):
    slope, intercept = line
    y1 = int(image.shape[0])# bottom of the image
    y2 = int(y1*2.5/5)      # slightly lower than the middle
    x1 = int((y1 - intercept)/slope)
    x2 = int((y2 - intercept)/slope)
    return [[x1, y1, x2, y2]]
 
# Our current lines are noisy from  
# the hough transform so we need to
# average out the lines to smooth it out.
def average_slope_intercept(image, lines):
    # Keeping an array to
    # track all positions.
    left_fit    = []
    right_fit   = []
    if lines is None:
        return None
    for line in lines:
        # These are the points for a line
        for x1, y1, x2, y2 in line:
            # polyfit returns the slope (m) and
            # intercept (b) for y = mx + b
            fit = np.polyfit((x1,x2), (y1,y2), 1)
            slope = fit[0]
            intercept = fit[1]
            # Remember we have two slopes
            # from the traffic lane. If the slope
            # from the two is negative (rise/run),
            # we're currently looking at the left lane.
            # Otherwise we're looking at the right lane.
            if slope < 0: # y is reversed in image
                left_fit.append((slope, intercept))
            else:
                # Positive slope.
                right_fit.append((slope, intercept))
    # Return smooth slopes
    # Using numpy functions to find the
    # average within the left and right slope.
    left_fit_average  = np.average(left_fit, axis=0)
    right_fit_average = np.average(right_fit, axis=0)
    # Place the new smooth slope on the new image.
    left_line  = make_points(image, left_fit_average)
    right_line = make_points(image, right_fit_average)
    # Return an array of the two new
    # lines placed on the image/frame.
    averaged_lines = [left_line, right_line]
    return averaged_lines

# Main program
cap = cv2.VideoCapture("test2.mp4")
while(cap.isOpened()):
    _, frame = cap.read()
    canny_image = canny(frame)
    cropped_canny = region_of_interest(canny_image)
    lines = houghLines(cropped_canny)
    averaged_lines = average_slope_intercept(frame, lines)
    line_image = display_lines(frame, averaged_lines)
    combo_image = addWeighted(frame, line_image)
    cv2.imshow("result", combo_image)
   
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()


Follow my socials:

Youtube:https://www.youtube.com/channel/UCU1qNFntn7dCi9uqyvrGKOg

Instagram: https://www.instagram.com/python.math/

Twitter:https://twitter.com/Pritish369


For any question or coding discussion, you can join my discord or telegram:

Discord:https://discord.gg/be7MmSuV

Telegram:https://t.me/Python_Math_Community



Comments

Popular posts from this blog

Create Ping Pong Game in Python

  Ping Pong Game: Table tennis , also known as  ping-pong  and  whiff-whaff , is a sport in which two or four players hit a lightweight ball, also known as the ping-pong ball, back and forth across a table using small rackets. The game takes place on a hard table divided by a net. Except for the initial serve, the rules are generally as follows: players must allow a ball played toward them to bounce once on their side of the table and must return it so that it bounces on the opposite side at least once. A point is scored when a player fails to return the ball within the rules. Play is fast and demands quick reactions. Spinning the ball alters its trajectory and limits an opponent's options, giving the hitter a great advantage. We can make it using pygame but I keep it more simple we will create this game using only the turtle module so let's drive into the code without wasting any time Code: # Import required library import turtle # Create screen sc = turtle . Screen () sc .

Draw Minecraft Charater in Python

  Minecraft  is a  sandbox video game  developed by the Swedish video game developer  Mojang Studios . The game was created by  Markus "Notch" Persson  in the  Java programming language . Following several early private testing versions, it was first made public in May 2009 before fully releasing in November 2011, with  Jens Bergensten  then taking over development.  Minecraft  has since been ported to several other platforms and is the  best-selling video game of all time , with over 238 million copies sold and nearly 140 million  monthly active users  as of 2021 . We gonna build a character of Minecraft using our creativity and coding skills so let's drive into the code: Code: import turtle as t def eye ( r , a ):     t . fillcolor ( 'brown' )     t . begin_fill ()     t . circle ( r , a )     t . end_fill () t . begin_fill () t . fillcolor ( '#8a00e6' ) t . penup () t . goto ( 0 ,- 50 ) t . pendown () t . right ( 90 ) t . f

How To Draw BMW Logo - In Python

 I know I don't need to introduce BMW as it is a very popular luxury car. Today we gonna draw the BMW logo in python. I know that you can draw it using a pencil and other tools like AutoCAD etc. But we are programmers we talk with computers so let's tell our computer to draw this logo for use with the help of python. Module The only module we will use is that turtle Code: import turtle as t t.begin_fill() t.fillcolor( '#008ac9' ) for i in range ( 50 ):     t.forward( 4 )     t.left( 2 ) t.right(- 80 ) t.forward( 116 ) t.right(- 90 ) t.forward( 132 ) t.end_fill() t.penup() t.pendown() t.right( 90 ) for i in range ( 50 ):     t.forward( 4 )     t.left(- 2 ) t.right( 80 ) t.forward( 116 ) t.forward(- 116 ) t.right( 90 ) t.begin_fill() t.fillcolor( '#008ac9' ) for j in range ( 45 ):     t.forward(- 4 )     t.left(- 2 ) t.right(- 90 ) t.forward( 116 ) t.end_fill() t.right( 180 ) t.forward( 116 ) t.right( 90 ) for i in range ( 47 ):     t.forward( 4 )     t.