Untitled
unknown
python
2 years ago
7.7 kB
7
Indexable
import cv2
import os
import matplotlib.pyplot as plt
from calibration_utils import calibrate_camera, undistort
from binarization_utils import binarize
from perspective_utils import birdeye
from line_utils import get_fits_by_sliding_windows, draw_back_onto_the_road, Line, get_fits_by_previous_fits
import numpy as np
from globals import xm_per_pix, time_window
# YOLOv4 setup
net = cv2.dnn.readNet("yolov4.weights", "yolov4.cfg")
net.setPreferableTarget(cv2.dnn.DNN_TARGET_OPENCL_FP16)
classes = []
with open("coco.names", "r") as f:
classes = [line.strip() for line in f.readlines()]
print(classes)
confidence_threshold = 0.5
nms_threshold = 0.4
processed_frames = 0
line_lt = Line(buffer_len=time_window)
line_rt = Line(buffer_len=time_window)
def detect_objects(frame):
height, width, channels = frame.shape
# Convert frame to blob for input to neural network
blob = cv2.dnn.blobFromImage(frame, 1/255, (416, 416), (0, 0, 0), swapRB=True, crop=False)
# Set input for neural network
net.setInput(blob)
# Get output layer names
layer_names = net.getLayerNames()
output_layers = [layer_names[layer_id - 1] for layer_id in net.getUnconnectedOutLayers()]
# Run forward pass through neural network
outputs = net.forward(output_layers)
# Initialize variables for object detection
boxes = []
confidences = []
class_ids = []
# Loop through outputs and detect objects
for output in outputs:
for detection in output:
scores = detection[5:]
class_id = np.argmax(scores)
confidence = scores[class_id]
if confidence > confidence_threshold:
center_x = int(detection[0] * width)
center_y = int(detection[1] * height)
w = int(detection[2] * width)
h = int(detection[3] * height)
# Rectangle coordinates
x = int(center_x - w / 2)
y = int(center_y - h / 2)
boxes.append([x, y, w, h])
confidences.append(float(confidence))
class_ids.append(class_id)
# Apply non-maximum suppression to eliminate overlapping boxes
indices = cv2.dnn.NMSBoxes(boxes, confidences, confidence_threshold, nms_threshold)
near_color =(0, 0, 255) # Red
far_color = (0, 255, 0) # Green
text_color = (255, 255, 255)
# Loop through indices and draw boxes and labels around objects
if len(indices) > 0:
for i in indices.flatten():
box = boxes[i]
x, y, w, h = box
# Determine center of box
center_x = int(x + w / 2)
center_y = int(y + h / 2)
# Determine if object is near or far based on y position
if center_y < 400:
color = far_color
text = "FAR"
else:
color = near_color
text = "NEAR"
# Draw box and label on frame
cv2.rectangle(frame, (x, y), (x + w, y + h), color, thickness=3)
cv2.putText(frame, f"{classes[class_ids[i]]} {confidences[i]:.2f} {text}", (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, text_color, thickness=2)
return frame
def prepare_out_blend_frame(blend_on_road, img_binary, img_birdeye, img_fit, line_lt, line_rt, offset_meter):
h, w = blend_on_road.shape[:2]
thumb_ratio = 0.2
thumb_h, thumb_w = int(thumb_ratio * h), int(thumb_ratio * w)
off_x, off_y = 20, 15
# add a gray rectangle to highlight the upper area
mask = blend_on_road.copy()
mask = cv2.rectangle(mask, pt1=(0, 0), pt2=(w, thumb_h+2*off_y), color=(0, 0, 0), thickness=cv2.FILLED)
blend_on_road = cv2.addWeighted(src1=mask, alpha=0.2, src2=blend_on_road, beta=0.8, gamma=0)
# add thumbnail of binary image
thumb_binary = cv2.resize(img_binary, dsize=(thumb_w, thumb_h))
thumb_binary = np.dstack([thumb_binary, thumb_binary, thumb_binary]) * 255
blend_on_road[off_y:thumb_h+off_y, off_x:off_x+thumb_w, :] = thumb_binary
# add thumbnail of bird's eye view
thumb_birdeye = cv2.resize(img_birdeye, dsize=(thumb_w, thumb_h))
thumb_birdeye = np.dstack([thumb_birdeye, thumb_birdeye, thumb_birdeye]) * 255
blend_on_road[off_y:thumb_h+off_y, 2*off_x+thumb_w:2*(off_x+thumb_w), :] = thumb_birdeye
# add thumbnail of bird's eye view (lane-line highlighted)
thumb_img_fit = cv2.resize(img_fit, dsize=(thumb_w, thumb_h))
blend_on_road[off_y:thumb_h+off_y, 3*off_x+2*thumb_w:3*(off_x+thumb_w), :] = thumb_img_fit
# add text (curvature and offset info) on the upper right of the blend
mean_curvature_meter = np.mean([line_lt.curvature_meter, line_rt.curvature_meter])
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(blend_on_road, 'Curvature radius: {:.02f}m'.format(mean_curvature_meter), (860, 60), font, 0.9, (255, 255, 255), 2, cv2.LINE_AA)
cv2.putText(blend_on_road, 'Offset from center: {:.02f}m'.format(offset_meter), (860, 130), font, 0.9, (255, 255, 255), 2, cv2.LINE_AA)
return blend_on_road
def process_pipeline(frame, keep_state=True):
global line_lt, line_rt, processed_frames
img_undistorted = undistort(frame, mtx, dist, verbose=False)
img_binary = binarize(img_undistorted, verbose=False)
img_birdeye, M, Minv = birdeye(img_binary, verbose=False)
# Lane detection
if processed_frames > 0 and keep_state and line_lt.detected and line_rt.detected:
line_lt, line_rt, img_fit = get_fits_by_previous_fits(img_birdeye, line_lt, line_rt, verbose=False)
else:
line_lt, line_rt, img_fit = get_fits_by_sliding_windows(img_birdeye, line_lt, line_rt, n_windows=9, verbose=False)
# Object detection
frame_with_objects = detect_objects(frame.copy())
offset_meter = compute_offset_from_center(line_lt, line_rt, frame_width=frame.shape[1])
blend_on_road = draw_back_onto_the_road(img_undistorted, Minv, line_lt, line_rt, keep_state)
# Overlay object detection on top of lane detection
blend_on_road = cv2.addWeighted(src1=blend_on_road, alpha=0.5, src2=frame_with_objects, beta=1, gamma=0)
blend_output = prepare_out_blend_frame(blend_on_road, img_binary, img_birdeye, img_fit, line_lt, line_rt, offset_meter)
processed_frames += 1
return blend_output
def compute_offset_from_center(line_lt, line_rt, frame_width):
if line_lt.detected and line_rt.detected:
line_lt_bottom = np.mean(line_lt.all_x[line_lt.all_y > 0.95 * line_lt.all_y.max()])
line_rt_bottom = np.mean(line_rt.all_x[line_rt.all_y > 0.95 * line_rt.all_y.max()])
lane_width = line_rt_bottom - line_lt_bottom
midpoint = frame_width / 2
offset_pix = abs((line_lt_bottom + lane_width / 2) - midpoint)
offset_meter = xm_per_pix * offset_pix
else:
offset_meter = -1
return offset_meter
if __name__ == '__main__':
# first things first: calibrate the camera
ret, mtx, dist, rvecs, tvecs = calibrate_camera(calib_images_dir='camera_cal')
# Open the webcam
cap = cv2.VideoCapture("input_video/input_video3.mp4") # 0 for default camera, you may need to change it based on your system
while True:
# Capture frame-by-frame
ret, frame = cap.read()
# Process the frame
blend = process_pipeline(frame, keep_state=False)
# Display the resulting frame
cv2.imshow('Frame', blend)
# Break the loop if 'q' key is pressed
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# When everything is done, release the capture
cap.release()
cv2.destroyAllWindows()Editor is loading...
Leave a Comment