Project 4
Code Logic:
- First we create a object for reading a video using VideoCapture() func.
- We set resolutions i.e., width and height. So, we convert them from float to integer
- As we know video is a series of images changing continously. We read the video frame by frame, one frame at a time which is nothing but a image.
- To the frame we apply basic thresholding. What exactly we do is : If the pixel value is smaller than the threshold, it is set to 0, otherwise it is set to a maximum value.
- Then for detecting the edges in the image we apply "Canny edge detection algorithm" by passing in the image obtained after thresholding, low_threshold and upper_threshold as parameters.
- We obtain region of interest by drawing a triangle over an image and return the masked image containing only the desired part of the canny image i.e.,region of interest.
- In the next step we apply Hough Line Transformation which is used to detect straight lines. It is done by passing cropped Canny image,rho,theta,minline_len & maxline_gap.
- If the straight lines are detected on the image, then we process it to average func and points func to find the coordinates of left and right lanes detected using the straight line equations y=mx+c.
- Next we draw the lines on the image where the left and right lanes are detected.
- Combine the image after drawing the lane markings and writing it on to the video.
I have attached the final output lane detected video.
#Importing the libraries
import cv2
import numpy as np
#Function for finding out the x and y coordinates
def points(image,line):
slope,intercept = line
#Calculating the y-coordinates
y1 = int(image.shape[0])
y2 = int(y1 * (3/5))
#Finding out the x coordinates y=mx+c -> x=(y-c)/m
x1 = int((y1-intercept)//slope)
x2 = int((y2-intercept)//slope)
return [[x1,y1,x2,y2]]
#Function to identify exact left and right lines coordinates
def average(image,lines):
left_fit = []
right_fit = []
for line in lines:
x1,y1,x2,y2 = line[0]
#Fit a polynomial of deg:1 to points(x,y)
fit = np.polyfit((x1,x2),(y1,y2),1)
slope = fit[0]
intercept = fit[1]
#Slope is negative for left lane and positive for right lane
if slope < 0:
left_fit.append((slope,intercept))
else:
right_fit.append((slope,intercept))
left_average = []
right_average = []
#If there are any points in the lists then taking weighted average of that along a particular axis
if len(left_fit) > 0:
left_average = np.average(left_fit,axis=0)
if len(right_fit) > 0:
right_average = np.average(right_fit,axis=0)
left_line = []
right_line = []
#If average is computed then finding out the points
if len(left_average)>0:
left_line = points(image,left_average)
if len(right_average)>0:
right_line = points(image,right_average)
#Appending the left & right lane points coordinates
averaged_lines = [left_line,right_line]
return averaged_lines
#Canny Edge Detection algorithm
def canny(image):
#Converting to gray image
gray = cv2.cvtColor(image, COLOR_BGR2GRAY)
#Applying gaussian filter to smoothen the image
blur = cv2.GaussianBlur(gray, (5, 5), 0)
#Canny function: image,low_thresh,high_thresh
canny_img = cv2.Canny(blur,50,150)
return canny_img
#Function for drawing lines over the video
def display_lines(image,lines):
line_image = np.zeros_like(image,dtype=np.uint8)
if lines is not None:
for line in lines:
for x1,y1,x2,y2 in line:
#line() func is used to draw a line on a image
#cv2.line(image,start_point,end_point,color=red,thickness=11)
cv2.line(line_image,(x1,y1),(x2,y2),(0,0,255),11)
return line_image
#Function for returning only the region of interest
def roi(canny):
height = canny.shape[0]
width = canny.shape[1]
mask = np.zeros_like(canny)
#Defining an array of endpoints of triangle
triangle = np.array([[(0,height),(width/2,height/2.11),(width,height)]],np.int32)
#Draw triangle over an image: 255 indicates color of triangle - white
cv2.fillPoly(mask,triangle,255)
#Bitwise '&' of Canny image and masked image
masked_image = cv2.bitwise_and(canny,mask)
return masked_image
#Create an object to read from camera
video = cv2.VideoCapture("Lane_video.mp4")
#To set resolutions.So, we convert them from float to integer.
frame_width = int(video.get(3))
frame_height = int(video.get(4))
size = (frame_width,frame_height)
#VideoWriter object will create a frame of above defined. The output is stored in 'lane_det_output.mp4' file.
result = cv2.VideoWriter('lane_det_output.mp4',cv2.VideoWriter_fourcc(*'MP4V'),10,size)
while(True):
_,frame = video.read()
#Break the loop if it doesn't contain frame
if frame is None:
break
#Apply the basic thresholding: If the pixel value is smaller than the threshold, it is set to 0, otherwise it is set to a maximum value.
no_noise = cv2.threshold(frame,200,255,cv2.THRESH_BINARY)[1]
#Edges detection in an image using the Canny algorithm
canny_image = cv2.Canny(no_noise,50,150)
#Region of interest
cropped_canny = roi(canny_image)
#Hough Transformation of lanes i.e.,lines
cropped_lines = cv2.HoughLinesP(cropped_canny,1,1*np.pi/180,50,np.array([]),minLineLength=15, maxLineGap=20)
if cropped_lines is not None:
averaged_lines = average(no_noise,cropped_lines)
line_image = display_lines(frame, averaged_lines)
#Combine image after drawing the lane markings 0.8 & 1.0 refers the opacity
combo_image = cv2.addWeighted(frame,0.8,line_image,1.0,1.0)
result.write(combo_image)
else:
continue
#release the video capture and video write objects
video.release()
result.release()
#Closes all the frames
cv2.destroyAllWindows()