本项目是笔者希望基于驾驶模拟类游戏 欧洲卡车模拟2(ETS2) 实现驾驶辅助系统的设想的一个基础项目 车道识别
《欧洲卡车模拟2》是一款模拟经营类游戏,在游戏中玩家要驾驶卡车完成货物运输任务,并可以购买更多的车库、卡车、挂车,从司机介绍所雇佣司机来为你工作,组建自己的物流公司。游戏中玩家可以改装自己的卡车、挂车的几乎每一个部件,从驾驶室到底盘到各种配件和内饰。穿越欧洲大陆,组建自己的运输帝国。
对于车道线检测,首先需要使程序能够检测出单张图片中的车道线,以此为依据进一步拓展至视频中的车道线检测,并最终推至实时画面中的车道线检测。
对于单张图片的车道线识别,我的思路如下:
我们默认摄像机在车内位置是不变的,因此路面在画面中的位置大致是不变的,为了降低噪声影响,我们可以人为选取路面位置作为兴趣区域,并对兴趣区域进行边缘检测与直线识别操作,并最终输出处理结果。
将原有的RGB三维色彩信息处理为一维的灰度值
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
灰度处理结果
降低图片噪声值,便于边缘检测
blur_ksize = 7
blur_gray = cv2.GaussianBlur(gray, (blur_ksize, blur_ksize), 1)
对图片进行边缘检测,便于下一步的霍夫直线检测
canny_lthreshold = 50
canny_hthreshold = 80
edges = cv2.Canny(blur_gray, canny_lthreshold, canny_hthreshold)
通过人为处理去除掉大部分的噪声值,便于直线检测
def roi_mask(img, np.array([[(0, 660), (0, img.shape[1]),(img.shape[1], img.shape[0]), (img.shape[1], 660) ,(1000, 560) ,(900, 560)]])):
# 生成roi目标区域,排除大部分无关噪声值
mask = np.zeros_like(img)
mask_color = 255
cv2.fillPoly(mask, vertices, mask_color)
masked_img = cv2.bitwise_and(img, mask)
return masked_img
通过霍夫变换将边缘图中的直线进行匹配,并在记录车道位置
rho = 1
theta = np.pi / 180
threshold = 15
min_line_length = 100
max_line_gap = 40
def draw_lines(img, lines, color=[255, 0, 0], thickness=16):
# 画线函数
for line in lines:
for x1, y1, x2, y2 in line:
cv2.line(img, (x1, y1), (x2, y2), color, thickness)
def hough_lines(img, rho, theta, threshold,min_line_len, max_line_gap):
# 生成线
lines = cv2.HoughLinesP(img, rho, theta, threshold, np.array([]),
minLineLength=min_line_len,
maxLineGap=max_line_gap)
line_img = np.zeros((img.shape[0], img.shape[1], 3), dtype=np.uint8)
draw_lines(line_img, lines)
return line_img
将车道位置与原图拼合,输出结果
img_res = cv2.add(img,line_img)
import matplotlib.pyplot as plt
import matplotlib.image as mplimg
import numpy as np
from cv2 import cv2
blur_ksize = 5 # Gaussian blur kernel size
canny_lthreshold = 50 # Canny edge detection low threshold
canny_hthreshold = 80 # Canny edge detection high threshold
# Hough transform parameters
rho = 1 #rho的步长,即直线到图像原点(0,0)点的距离
theta = np.pi / 180 #theta的范围
threshold = 15 #累加器中的值高于它时才认为是一条直线
min_line_length = 150 #线的最短长度,比这个短的都被忽略
max_line_gap = 40 #两条直线之间的最大间隔,小于此值,认为是一条直线
def roi_mask(img, vertices):
# 生成roi目标区域,排除大部分无关噪声值
mask = np.zeros_like(img)
mask_color = 255
cv2.fillPoly(mask, vertices, mask_color)
masked_img = cv2.bitwise_and(img, mask)
return masked_img
def draw_lines(img, lines, color=[255, 0, 0], thickness=16):
# 画线函数
for line in lines:
for x1, y1, x2, y2 in line:
cv2.line(img, (x1, y1), (x2, y2), color, thickness)
def hough_lines(img, rho, theta, threshold,min_line_len, max_line_gap):
# 生成线
lines = cv2.HoughLinesP(img, rho, theta, threshold, np.array([]),
minLineLength=min_line_len,
maxLineGap=max_line_gap)
line_img = np.zeros((img.shape[0], img.shape[1], 3), dtype=np.uint8)
draw_lines(line_img, lines)
return line_img
def img_rogress(img):
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
blur_gray = cv2.GaussianBlur(gray, (blur_ksize, blur_ksize), 1)
edges = cv2.Canny(blur_gray, canny_lthreshold, canny_hthreshold)
return edges
if __name__ == "__main__":
img = mplimg.imread("datapic/test (26).jpg")
roi_vtx = np.array([[(0, 660), (0, img.shape[1]),(img.shape[1], img.shape[0]), (img.shape[1], 660) ,(1000, 560) ,(900, 560)]])
pre_res = img_rogress(img)
roi_edges = roi_mask(pre_res,roi_vtx)
line_img = hough_lines(roi_edges, rho, theta, threshold,
min_line_length, max_line_gap)
img_res = cv2.add(img,line_img)
plt.imshow( img_res)
plt.show()
经过后面的一系列探索,本方法存在很大的局限性,未来将会更新另一种新的车道检测方法。