Opencv|Road Lane Line Detection
Today, I want to share a program of detection for road lane line in an image.
In a similar way, we can also detect road lane line in a video.(Seen in the Extra Expansion part)
step 1. import the image and show it in pyplot.
import matplotlib.pyplot as plt
import cv2
import numpy as np
image= cv2.imread('road.jpeg')#375*500
image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
#the order of colors is different in pyplot and opencv.
#So we need to transform the color of the original image.
print(image.shape)
height = image.shape[0]
width=image.shape[1]
plt.imshow(image)
plt.show()
result:
(375, 500, 3)
Step2. Determine the detection area.
I created a function called region_of_interest to get the area to remove the extra part of the image, leaving only the part to be detected.
Besides, I created an array named region_of_interest_vertices to save the vertices of the area I wanted to keep.
Details can be seen in the notes of the code below.
def region_of_interest(img,vertices):
mask =np.zeros_like(img)
#create an array as large as the original image.
match_mask_color = 255
# the color filled in the area.
cv2.fillPoly(mask,vertices,match_mask_color)
# fill mask with the color match_mask_color in detection region in mask.
masked_image=cv2.bitwise_and(img,mask)
#combine img and mask to get rid of the unneccessary part for detection in image.
return masked_image
region_of_interest_vertices = [
(100,height),
(280,275),
(width,height)]
#To define the vertices of the region we need to detect.
Step 3. Perform preliminary processing on the image
gray_image=cv2.cvtColor(image,cv2.COLOR_RGB2GRAY)
#turn the image to gray which is easier to detect.
canny_image=cv2.Canny(gray_image,100,200)
#Use the function Canny to find outlines of objects in the detected area.
cropped_image = region_of_interest(canny_image,np.array([region_of_interest_vertices],np.int32))
#to get the region picture we need.(shown as the picture below)
result:
Step 4.Use HoughLinesP to detect the lines in cropped_image.
Parameters in HoughLinesP:
rho :the resolution of the parameter polar diameter r in pixels.
theta: the polar angle \ theta resolution in radians
threshold: the minimum number of curve intersections needed to detect a straight line.
lines :a container storing the parameter pairs (x_ {start}, y_ {start}, x_ {end}, y_ {end}) of the detected straight lines.( the coordinates of the two end points of the line segment)
minLineLength: the minimum number of points that can form a straight line. A straight line with insufficient number of points will be discarded.
maxLineGap:the maximum distance of bright points that can be considered on a straight line.
lines=cv2.HoughLinesP(cropped_image,rho=6,theta=np.pi/180,threshold=140,lines=np.array([]), minLineLength=60,maxLineGap=30)
Step 5. Draw the detected straight lines in the original image.
Details can be seen in the notes of the code below.
def draw_the_lines(img,lines):#to draw the lines in img
img=np.copy(img)
blank_image= np.zeros((img.shape[0],img.shape[1],3),dtype=np.uint8)
#create an blank_image as large as img
for line in lines:
for x1,y1,x2,y2 in line:
cv2.line(blank_image,(x1,y1),(x2,y2),(0,255,0),
thickness=3)
#draw lines in blank_image
img = cv2.addWeighted(img,0.8,blank_image,1,0.0)
#combine the img and blank_image
return img
img_with_lines=draw_the_lines(image,lines)
Step 6. Print the image we got in the end.
plt.title('img_with_lines')
plt.imshow(img_with_lines)
plt.show()
result:
Extra Expansion
With minor changes, the program can be applied to videos to detect lane lines.
import matplotlib.pylab as plt
import cv2
import numpy as np
def region_of_interest(img, vertices):
mask = np.zeros_like(img)
match_mask_color = 255
cv2.fillPoly(mask, vertices, match_mask_color)
masked_image = cv2.bitwise_and(img, mask)
return masked_image
def drow_the_lines(img, lines):
img = np.copy(img)
blank_image = np.zeros((img.shape[0], img.shape[1], 3), dtype=np.uint8)
for line in lines:
for x1, y1, x2, y2 in line:
cv2.line(img, (x1, y1), (x2, y2), (0, 255, 255), thickness=3)
img = cv2.addWeighted(img, 0.8, blank_image, 1, 0.0)
return img
def process(image):
print(image.shape)
height=image.shape[0]
width=image.shape[1]
region_of_interest_vertices =[
(0,height),
(width/2,height/1.75),
(width,height)
]
gray_image= cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
canny_image=cv2.Canny(gray_image,100,200)
cropped_image = region_of_interest(canny_image,np.array([region_of_interest_vertices],np.int32))
lines =cv2.HoughLinesP(cropped_image,
rho=6,theta=np.pi/180,
threshold=160,
lines=np.array([]),
minLineLength=0,
maxLineGap=25
)
image_with_lines=drow_the_lines(image,lines)
return image_with_lines
cap = cv2.VideoCapture('solidWhiteRight.avi')
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()
result:
优快云 does not support uploading video so it is displayed in screenshot form.
Gains:
At first, the initial setting of those parameters bothered me a lot. It is difficult to find the most suitable parameter values. After a long groping with several tries, finally I found the parameters that were sufficient to achieve the purpose. But the accuracy of recognition is still not enough, which can be further optimized.
Thank you for reading!
Resources:
https://www.bilibili.com/video/av77215007?
https://blog.youkuaiyun.com/e01528/article/details/82749816
test video footage from:
https://github.com/naokishibuya/car-finding-lane-lines