使用OpenCV对车道进行实时检测的实现示例代码

1. 简介

OpenCV是一个流行的开源计算机视觉库,它包含了各种图像处理和计算机视觉算法。本文将展示如何使用OpenCV来进行车道检测,并对其进行实时跟踪。车道检测是自动驾驶汽车中非常重要的一步,通过对车道的检测,我们可以确定车辆的位置和朝向,从而更好地进行导航。

2. 实现过程

2.1 准备工作

在开始编写代码之前,需要先安装OpenCV库,并准备好测试用的视频。在本文中,我将使用名为lanelines.mp4的测试视频。

2.2 视频读取与显示

首先,我们需要读取视频,并将其显示出来。下面是相关代码:

import cv2

video = cv2.VideoCapture('lanelines.mp4')

while True:

ret, frame = video.read()

if not ret:

break

cv2.imshow('Video', frame)

if cv2.waitKey(1) == ord('q'):

break

video.release()

cv2.destroyAllWindows()

上述代码中,我们使用了cv2.VideoCapture()函数来读取视频文件,这个函数会返回一个VideoCapture对象,我们可以使用该对象来读取视频的每一帧。在每一帧读取完成后,我们可以调用cv2.imshow()函数将其显示在屏幕上。如果用户输入了q键,则退出程序并关闭所有窗口。

需要注意的一点是,在使用cv2.imshow()之前,需要先使用cv2.namedWindow()函数来创建窗口,否则程序会无响应。

2.3 预处理

接下来,我们需要对每一帧进行预处理,以便于后续的车道检测。我们需要完成以下几个步骤:

将图像转换为灰度图像

应用高斯模糊

使用Canny算法检测边缘

选择感兴趣区域,并进行掩码操作,以便于仅保留车道线段

下面是完整代码:

import cv2

import numpy as np

video = cv2.VideoCapture('lanelines.mp4')

while True:

ret, frame = video.read()

if not ret:

break

# 将图像转换为灰度图像

gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

# 应用高斯模糊

kernel_size = 5

blur_gray = cv2.GaussianBlur(gray, (kernel_size, kernel_size), 0)

# 使用Canny算法检测边缘

low_threshold = 50

high_threshold = 150

edges = cv2.Canny(blur_gray, low_threshold, high_threshold)

# 选择感兴趣区域,并进行掩码操作,以便于仅保留车道线段

mask = np.zeros_like(edges)

ignore_mask_color = 255

imshape = frame.shape

vertices = np.array([[(0, imshape[0]), (460, 320), (520, 320), (imshape[1], imshape[0])]], dtype=np.int32)

cv2.fillPoly(mask, vertices, ignore_mask_color)

masked_edges = cv2.bitwise_and(edges, mask)

cv2.imshow('Video', masked_edges)

if cv2.waitKey(1) == ord('q'):

break

video.release()

cv2.destroyAllWindows()

在以上代码中,我们使用cv2.cvtColor()函数将图像从BGR格式转换为灰度图像格式,使用cv2.GaussianBlur()函数对其进行高斯模糊处理,使用cv2.Canny()函数检测边缘。我们还定义了一个用于选择感兴趣区域的多边形,将图片分为了矩形区域和梯形区域两部分(mask可自由设置,位置应该包含车道线部分),并使用cv2.fillPoly()函数进行掩码操作,仅保留车道线段。

2.4 车道检测

在对每一帧图像进行预处理后,我们就可以进行车道检测了。我们将使用霍夫变换和二次函数拟合来检测车道线。下面是代码:

import cv2

import numpy as np

video = cv2.VideoCapture('lanelines.mp4')

while True:

ret, frame = video.read()

if not ret:

break

# 将图像转换为灰度图像

gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

# 应用高斯模糊

kernel_size = 5

blur_gray = cv2.GaussianBlur(gray, (kernel_size, kernel_size), 0)

# 使用Canny算法检测边缘

low_threshold = 50

high_threshold = 150

edges = cv2.Canny(blur_gray, low_threshold, high_threshold)

# 选择感兴趣区域,并进行掩码操作,以便于仅保留车道线段

mask = np.zeros_like(edges)

ignore_mask_color = 255

imshape = frame.shape

vertices = np.array([[(0, imshape[0]), (460, 320), (520, 320), (imshape[1], imshape[0])]], dtype=np.int32)

cv2.fillPoly(mask, vertices, ignore_mask_color)

masked_edges = cv2.bitwise_and(edges, mask)

# 霍夫变换检测线段,并拟合二次函数

rho = 2

theta = np.pi/180

threshold = 40

min_line_length = 10

max_line_gap = 20

lines = cv2.HoughLinesP(masked_edges, rho, theta, threshold, np.array([]),

min_line_length, max_line_gap)

left_fit = []

right_fit = []

for line in lines:

for x1, y1, x2, y2 in line:

slope = (y2 - y1) / (x2 - x1)

if abs(slope) < 0.5:

continue

if slope < 0:

left_fit.append((x1, y1))

left_fit.append((x2, y2))

else:

right_fit.append((x1, y1))

right_fit.append((x2, y2))

if len(left_fit) > 0 and len(right_fit) > 0:

left_fit_x, left_fit_y = zip(*left_fit)

right_fit_x, right_fit_y = zip(*right_fit)

left_fit_curve = np.polyfit(left_fit_y, left_fit_x, 2)

right_fit_curve = np.polyfit(right_fit_y, right_fit_x, 2)

plot_y = np.linspace(0, frame.shape[0] - 1, frame.shape[0])

left_fit_x = left_fit_curve[0] * plot_y ** 2 + left_fit_curve[1] * plot_y + left_fit_curve[2]

right_fit_x = right_fit_curve[0] * plot_y ** 2 + right_fit_curve[1] * plot_y + right_fit_curve[2]

blank = np.zeros_like(frame)

color = [0, 255, 0]

thickness = 10

left_line = np.array(list(zip(left_fit_x, plot_y)), np.int32)

right_line = np.array(list(zip(right_fit_x, plot_y)), np.int32)

cv2.polylines(blank, [left_line], False, color, thickness)

cv2.polylines(blank, [right_line], False, color, thickness)

result = cv2.addWeighted(frame, 0.8, blank, 1, 0)

cv2.imshow('Video', result)

else:

cv2.imshow('Video', frame)

if cv2.waitKey(1) == ord('q'):

break

video.release()

cv2.destroyAllWindows()

在以上代码中,我们首先使用cv2.HoughLinesP()函数检测线段,然后筛选出斜率在0.5到正无穷之间的线段,分别存入左侧车道和右侧车道的列表中。接着,我们使用np.polyfit()函数对左侧车道和右侧车道的线段进行二次函数拟合,得到其拟合曲线。最后,我们使用cv2.polylines()函数将拟合曲线画在一张全黑的背景上。需要注意的是,在进行车道检测时,我们需要在相邻帧之间进行线段匹配,以便于产生平滑的车道线。

3. 结论

本文介绍了如何使用OpenCV来进行车道检测,其中包括视频读取与显示、预处理(灰度化、高斯模糊、Canny检测、掩码),以及车道检测(霍夫变换、二次函数拟合)。欢迎读者在自己的项目中尝试使用这些技术。

后端开发标签