Project 4
# Python
# Programmer: Mark Omefe
# Date:01/11/2022
# Hough Transform for Lane detection
import cv2
import numpy as np
import matplotlib.pyplot as plt
import math
import warnings
from scipy import spatial
from PIL import Image
warnings.filterwarnings('ignore')
#function to convert BGR image to Gray
def gray_image(image):
return cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
#function to apply Gaussian filter on Gray Image
def gaussian_filter(image, filter_size, sigma):
return cv2.GaussianBlur(image, (filter_size, filter_size), sigma)
#function to detect edges using Canny Edge Detector
def canny_edge_detection(image, low_threshold, high_threshold):
return cv2.Canny(image, low_threshold, high_threshold)
#To find just region of interest in the image
def ROI_masking(image):
height = image.shape[0]
width = image.shape[1]
image = np.array(image, dtype=np.float32)
polygon_coords = np.array([(0, height), (0, round(height/1.25)), (round(width/2),round(height/2)),(width, height)])
mask = np.zeros((height, width))
masked_image = cv2.fillPoly(mask, [polygon_coords], 255)
masked_image = np.array(masked_image, dtype=np.float32)
return cv2.bitwise_and(image, masked_image)
#To find hough lines using hough transformation
def hough_transformation(reg_of_int_img):
image = cv2.convertScaleAbs(reg_of_int_img)
return cv2.HoughLinesP(image, 1, np.pi/180, 50, None, 0, 1000)
#To get the get ordinates of lines on lanes
def get_coordinates(image, parameters):
slope, intercept = parameters
if slope<0:
y1 = image.shape[0]
y2 = int(y1*(3/5))
x1 = np.clip(int((y1-intercept)/slope), 0, image.shape[1])
x2 = int((y2-intercept)/slope)
else:
y1 = image.shape[0]
y2 = int(y1*(3/5))
x1 = int((y1-intercept)/slope*0.98)
x2 = int((y2-intercept)/slope)
return np.array([x1, y1, x2, y2])
#Function to define slope and intercept to find coordinates for left lines and right lines
def average_slope_intercept(image, lines):
left_lines = []
right_lines = []
#following for loop is to get slope and intercept
for line in lines:
x1, y1, x2, y2 = line[0][:]
parameters = np.polyfit((x1,x2), (y1,y2), 1)
slope = parameters[0]
intercept = parameters[1]
if slope < 0:
left_lines.append((slope, intercept))
else:
right_lines.append((slope, intercept))
#Left Line COordinates
left_line_coordinates = []
for line in left_lines:
if line[0] > -0.1:
continue
left_line_coordinates.append(get_coordinates(image, line))
#Right line coordinates
right_line_coordinates = []
for line in right_lines:
if line[0] < 0.2:
continue
right_line_coordinates.append(get_coordinates(image, line))
# getting left lines and right lines using cosine distance remove the crackline that could be found on the road
final_left_lines = []
final_right_lines = []
cosine_distance = []
# Condition if both curves have the same slope
if len(left_line_coordinates) == 0 or len(right_line_coordinates) == 0:
if len(left_line_coordinates) == 0:
lines = right_line_coordinates
else:
lines = left_line_coordinates
if len(lines) <= 2:
return np.array(lines)
# Calculating the cosine distance between the left line and right line
for l in lines:
for m in lines:
cosine_distance.append(spatial.distance.cosine(l, m))
cosine_distance = [item for item in cosine_distance if not(math.isnan(item))]
threshold = np.percentile(cosine_distance,85)
# Filter the lines based on threshold and cosine distance with 85 percentile
for left in lines:
for right in lines:
dist = spatial.distance.cosine(left, right)
if dist > threshold and len(final_left_lines) == 0:
final_left_lines.append(list(left))
final_right_lines.append(list(right))
continue
if dist > threshold:
if list(left) not in final_left_lines and list(left) not in final_right_lines:
final_left_lines.append(list(left))
if list(right) not in final_right_lines and list(right) not in final_right_lines:
final_right_lines.append(list(right))
# To find the average of the lines
left_line = np.average(np.array(final_left_lines), axis=0)
right_line = np.average(np.array(final_right_lines), axis=0)
return np.array([left_line, right_line])
else:
# To keep the farthest lines and removing crack lines
for left in left_line_coordinates:
for right in right_line_coordinates:
cosine_distance.append(spatial.distance.cosine(left, right))
cosine_distance = [item for item in cosine_distance if not(math.isnan(item))]
threshold = np.percentile(cosine_distance,85)
# Threshold filtering similar to NVM
for left in left_line_coordinates:
for right in right_line_coordinates:
dist = spatial.distance.cosine(left, right)
if dist > threshold and len(final_left_lines) == 0:
final_left_lines.append(list(left))
final_right_lines.append(list(right))
continue
if dist > threshold:
if list(left) not in final_left_lines:
final_left_lines.append(list(left))
if list(right) not in final_right_lines:
final_right_lines.append(list(right))
left_line = np.average(np.array(final_left_lines), axis=0)
right_line = np.average(np.array(final_right_lines), axis=0)
return np.array([left_line, right_line])
# Function to draw lines on the lanes for each side of the road
def draw_lane_lines(image, lines, color=[0, 0, 255], thickness=10):
line_image = np.zeros_like(image)
for line in lines:
x1, y1, x2, y2 =line
if line is not None:
cv2.line(line_image, (int(x1),int(y1)), (int(x2),int(y2)), color, thickness)
return cv2.addWeighted(image, 0.8, line_image, 1.0, 1.0)
# Recursive Function that performs lane using all the above functions on the image and find lanes
def lanes(image):
#gray image
gray_images = gray_image(image)
#Gaussian Filtering or smoothing
gaussian_filtered_image = gaussian_filter(gray_images, 5, 5)
#Canny edge detection
canny_edge_image = canny_edge_detection(gaussian_filtered_image, 50, 150)
#region of interest
ROI_image = ROI_masking(canny_edge_image)
#To get hough lines
hough_lines = hough_transformation(ROI_image)
#to get left and right lines
lines = average_slope_intercept(ROI_image, hough_lines)
threshold = spatial.distance.cosine(lines[0], lines[1])
#to draw lanes using above lines
draw_lanes = draw_lane_lines(image, lines,[0, 0, 255], 10)
return threshold, draw_lanes
#Applying above functions on Input given Video to detect lanes
# Reading the input video
video = cv2.VideoCapture('Lane_video.mp4')
# Check for the fps of video
fps = video.get(5)
# Checking for the total number of frames in the video
frame_count = video.get(7)
# Getting the frame size data
frame_width = int(video.get(3))
frame_height = int(video.get(4))
frame_size = (frame_width,frame_height)
# Impressing lane marked images into a video file
output = cv2.VideoWriter('Road Lane Tracking.avi',cv2.VideoWriter_fourcc('M','J','P','G'), 20, frame_size)
# loading of each frame
while(video.isOpened()):
ret, frame = video.read()
if ret == True:
threshold, final_image = lanes(frame)
if 0.2 <= threshold <= 0.303:
output.write(final_image)
cv2.imshow("Road Lane Tracking",final_image)
k = cv2.waitKey(50)
if k == 113:
break
else:
continue
else:
break
import cv2
import numpy as np
# Hough Transform for static lane detection image
#function to convert read image
def read_image(image_path):
"""This function reads any image from a given path"""
image = cv2.imread(image_path)
return image
def save_image(image_name_format, image):
"""This function saves any image to a given path"""
cv2.imwrite(image_name_format, image)
#function to convert BGR image to Gray
def gray_scale(image):
converted_image = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
return converted_image
#function to apply Gaussian filter on Gray Image
def guassin_filter(image, kernel_dimensions):
filtered_image = cv2.GaussianBlur(image, kernel_dimensions, 0)
return filtered_image
#function to detect edges using Canny Edge Detector
def canny_edge_detector(image, lower_threshold, upper_threshold):
canny_detected_edge = cv2.Canny(image, lower_threshold, upper_threshold)
return canny_detected_edge
def ROI_polygon(image):
mask = np.zeros_like(image)
if len(image.shape) > 2:
channel_count = image.shape[2]
ignore_mask_color = (255,)*channel_count
else:
ignore_mask_color = 255
rows = image.shape[0]
columns = image.shape[1]
bottom_left = [0, rows]
top_left = [columns*0.5, rows*0.5]
bottom_right = [columns*0.9, rows*0.95]
top_right = [columns*0.6, rows*0.6]
vertices = np.array([[bottom_left,top_left,top_right,bottom_right]], dtype=np.int32)
cv2.fillPoly(mask,vertices,ignore_mask_color)
masked_image = cv2.bitwise_and(image,mask)
return masked_image
#To find just region of interest in the image
def ROI_masking(image):
height = image.shape[0]
width = image.shape[1]
image = np.array(image, dtype=np.float32)
polygon_coordinates = np.array([(0,height),(round(width/2),round(height/2)),(1000,height)])
mask = np.zeros((height,width))
masked_image1 = cv2.fillPoly(mask,[polygon_coordinates],255)
masked_image2 = np.array(masked_image1,dtype=np.float32)
masked_image3 = cv2.bitwise_and(image,masked_image2)
return masked_image3
#Function to define slope and intercept to find coordinates for left lines
def average_slope_intercept(image,lines):
left_lines = []
right_lines = []
for line in lines:
parameters = np.polyfit((x1,x2),(y1,y2),1)
slope = parameters[0]
y_intercept = parameters[1]
if slope < 0:
left_lines.append((slope,y_intercept))
else:
right_lines.append((slope,y_intercept))
#Left Line COordinates
left_average = np.average(left_lines, axis=0)
right_average = np.average(right_lines, axis=0)
left_line = get_coordinates(image,left_average)
right_line = get_coordinates(image,right_average)
return np.array([left_line, right_line])
#To get the get coordinates of lines on lanes
def get_coordinates(image, parameters):
slope, intercept = parameters
if slope < 0:
y1 = image.shape[0]
y2 = int(y1*(3/5))
x1 = np.clip(int(((y1-intercept)/slope)),50,image.shape[1])
x2 = int((y2-intercept)/slope)
else:
y1 = image.shape[0]
y2 = int(y1*(3/5))
x1 = int((y1-intercept)/slope*0.82)
x2 = int((y2-intercept)/slope)
return np.array([x1,y1,x2,y2])
#function to draw lines on lanes either side of the road
def draw_lane_lines(image,lines,color,thickness):
line_image = np.zeros_like(image)
for line in lines:
x1,y1,x2,y2 = line
if line is not None:
cv2.line(line_image,(x1,y1),(x2,y2),color,thickness)
return cv2.addWeighted(image,0.8,line_image,1.0,1.0)
#To find hough lines using hough transformation
def hough_transformation(region_of_interest):
image = cv2.convertScaleAbs(region_of_interest)
return cv2.HoughLinesP(image, 1, np.pi/180, 50, None, 0, 1000)
dims = (5,5)
l_limit = 50
u_limit = 150
line_color = [0,0,255]
line_thickness = 12
image = read_image('road lane.jpg')
gray_images = gray_scale(image)
cv2.imshow('gray image',gray_images)
cv2.waitKey(0)
save_image('gray_image.jpg', gray_images)
filtered_image = guassin_filter(image=gray_images, kernel_dimensions=dims)
cv2.imshow('filtered image',np.hstack((gray_images,filtered_image)))
cv2.waitKey(0)
save_image('filtered_image.jpg', filtered_image)
canny_edge_image = canny_edge_detector(image, lower_threshold=l_limit, upper_threshold=u_limit)
cv2.imshow('edge image',np.hstack((filtered_image, canny_edge_image)))
cv2.imshow('edge image',canny_edge_image)
cv2.waitKey(0)
save_image('edge_image.jpg', canny_edge_image)
https://drive.google.com/drive/folders/1Fm-iDUVfY8SNuKJThLZV6aJptIwRPfEp?usp=sharing