Road lane detection using OpenCV
Let’s implement a road lane detector using OpenCV.
We would be using Canny Edge Detector and Hough Lines for the same. Their functions can be implemented using OpenCV.
For the working of Canny Edge Detector from scratch, check out my last article in which I gave an in-depth explanation for it. Canny Edge Detector plays a vital role in this model, hence having its knowledge helps.
MODEL PIPELINE
First of all let’s import Matplotlib, OpenCV, and Numpy libraries. For those, who don’t know Matplotlib is a visualization tool whereas OpenCV is an image processing library.
import matplotlib.pylab as plt
import cv2
import numpy as np
Now, the pipeline of the model will be as follows:
1. Read the image and convert it to RGB format. Get its height and width and define a region of interest which is required for the Lane Detection.
2. Then convert the image to GRAY format because the Canny Edge Detector takes only GRAY images as input. Pass the image to Canny Edge Detector.
3. Now, mask the image by the region of interest defined earlier.
4. Then apply Hough transform to the image which is a feature extraction technique that gives instances of objects within a certain class of shapes. In our case, the shape will be a line thus we will use HoughLines function.
5. Finally, the transform will return the detected lines and we will draw it in our image as output.
Now let’s make a helper function which masks the image to the region of interest. One can proceed without doing so but this helps to achieve better results. We are simply defining our region of interest in the image.
We can mask the image by giving vertices and input image to the function.
def region_of_interest(img,vertices):
mask = np.zeros_like(img)
channel_count=img.shape[2]
match_mask_color= 255 #(255,) * channel_count
cv2.fillPoly(mask,vertices,match_mask_color)
masked_image=cv2.bitwise_and(img,mask)
return masked_image
Also, let’s implement a helper function that draws given lines on the image. The lines needed to be drawn will be available after Hough Transform.
def draw_the_lines(img,lines):
imge=np.copy(img)
blank_image=np.zeros((imge.shape[0],imge.shape[1],3),\
dtype=np.uint8)
for line in lines:
for x1,y1,x2,y2 in line:
cv2.line(blank_image,(x1,y1),(x2,y2),(0,255,0),thickness=3)
imge = cv2.addWeighted(imge,0.8,blank_image,1,0.0)
return imge**Note: Mind the indents, as it could differ for your IDE. Code link would be provided at the end.
cv2.line() is used to draw lines on the blank image, which is added to the original image via cv2.addWeighted().
To read further about these functions refer to the original documentation.
Probabilistic Hough Line Transform
Let’s understand the Probabilistic Hough Line Transform. If you are not interested in the theory you can skip this section.
Hough Transform is a popular technique to detect any shape if you can represent that shape in mathematical form. It can detect the shape even if it is broken or distorted a little bit.
For in-depth understanding, refer to the official documentation.
In short, a line can be represented as p= x cosQ + y sinQ, where p is the perpendicular distance and Q is the angle made by it with the x-axis.
In Hough Line Transform, we create an array with two columns and multiple rows where columns denote values of p and Q which are initially set to zero.
Size of the array depends on the accuracy we want, Now from a given Canny Edge image we iterate these different values of p and Q all over the edge points and deduce best continuous lines and save that value of p and Q. Later this will be used for drawing lines on the original image.
Probabilistic Hough Transform is an optimization of Hough Transform. It doesn’t take all the edge points into consideration, instead, take only a random subset of points and that is sufficient for line detection.
cv2.HoughLinesP(edges,rho,theta,threshold,minLineLength,maxLineGap)
‘edges’ is the edge image, ‘rho’ is p or the perpendicular distance.
‘np.pi/180’ is the range of theta or the angle in radians, here -180 to 180.
‘threshold’ needs to be fine-tuned according to the image.
‘minLineLength’ is the minimum length of the line, Line segments shorter than this are rejected.
‘maxLinGap’ is the maximum allowed gap between the line segments to treat them as single line.
The input image used is:
Step1: Read the image and convert it to RGB format. Get its height and width and define a region of interest which is required for the Lane Detection.
image=cv2.imread('img.png')
image=cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
height=image.shape[0]
width=image.shape[1]
region_of_interest_coor=[(0,height),(0,400),(width/2,height/3),\
(width,height)]
Step2: Convert the image to GRAY format and pass the image to Canny.
gray_image = cv2.cvtColor(image,cv2.COLOR_RGB2GRAY)
canny_image = cv2.Canny(gray_image,100,200)
Step3: Now, mask the canny image by the region of interest defined earlier.
cropped=region_of_interest(canny_image,\
np.array([region_of_interest_coor],np.int32))
Step4: Apply Probabilistic Hough Line Transform to the masked canny image.
lines = cv2.HoughLinesP(cropped,rho=2,theta=np.pi/120,threshold=120\
,lines=np.array([]),minLineLength=20,maxLineGap=35)
Step5: Draw the lines by draw_the_lines() defined earlier, by using ‘lines’ returned by the HoughLinesP() and plot the resultant image.
image_with_lines = draw_the_lines(image,lines) plt.imshow(image_with_lines)
plt.show()
This sums up the implementation of the model. Here is the code.
This can be easily scaled up for video or real-time. We just need to use cv2.VideoCapture(‘vid.mp4’) function which returns frame by frame image and each image can be passed through the model we just created.
cap = cv2.VideoCapture('video.mp4')while cap.isOpened():
ret, frame = cap.read()
frame = process(frame)
cv2.imshow('frame', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break cap.release()
cv2.destroyAllWindows()
‘cap’ has every frame of the image which passed through the function process() i.e the Lane Detection model we created.
I’ve already implemented it and the code can be found here.
Finally, I wanted to acknowledge Programming Knowledge for their work.
Thank you for reading, If you liked this article, do clap and you can read more such articles here.
Cheers!
Happy Learning!