做完项目后写了个技术小结,供自己回顾也为他人学习提供参考。
另外准备建一个无人驾驶方面的微信交流群,有兴趣的朋友可以加我微信:wxl609278502 请注明: 姓名-单位/学校
项目描述:
使用opencv实时处理车载摄像机采集的道路图像,检测当前的车道,并计算出当前车辆偏离车道中心的距离,计算当前车道的曲率。
项目代码GitHub地址:https://github.com/xlwang123/SEU_LaneDetect
附几张高速公路直道和匝道弯道的检测效果图:
测试地点:南京
软硬件要求
- 普通车载记录仪(要求畸变不严重,对于畸变严重的需要进行图片校正)
- 工控机(带GPU更好,没有GPU也无所谓)
- Ubuntu16.04 + opencv3.2
实现步骤
- 图片校正(对于相机畸变较大的需要先计算相机的畸变矩阵和失真系数,对图片进行校正)
- 截取感兴趣区域,仅对包含车道线信息的图像区域进行处理
- 使用透视变换,将感兴趣区域图片转换成鸟瞰图
- 针对不同颜色的车道线,不同光照条件下的车道线,不同清晰度的车道线,根据不同的颜色空间使用不同的梯度阈值,颜色阈值进行不同的处理。并将每一种处理方式进行融合,得到车道线的二进制图。
- 提取二进制图中属于车道线的像素
- 对二进制图片的像素进行直方图统计,统计左右两侧的峰值点作为左右车道线的起始点坐标进行曲线拟合。
- 使用二次多项式分别拟合左右车道线的像素点(对于噪声较大的像素点,可以进行滤波处理,或者使用随机采样一致性算法进行曲线拟合)。
- 计算车道曲率及车辆相对车道中央的偏离位置。
- 效果显示(可行域显示,曲率和位置显示)。
相机校正
这里会使用opencv提供的方法通过棋盘格图片组计算相机校正矩阵(camera calibration matrix)和失真系数(distortion coefficients)。首先要得到棋盘格内角的世界坐标”object points”和对应图片坐标”image point”。
假设棋盘格内角世界坐标的z轴为0,棋盘在(x,y)面上,则对于每张棋盘格图片组的图片而言,对应”object points”都是一样的。而通过使用openCv的cv2.findChessboardCorners(),传入棋盘格的灰度(grayscale)图片和横纵内角点个数就可得到图片内角的”image point”。
def get_obj_img_points(images,grid=(9,6)):
object_points=[]
img_points = []
for img in images:
#生成object points
object_point = np.zeros( (grid[0]*grid[1],3),np.float32 )
object_point[:,:2]= np.mgrid[0:grid[0],0:grid[1]].T.reshape(-1,2)
#得到灰度图片
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#得到图片的image points
ret, corners = cv2.findChessboardCorners(gray, grid, None)
if ret:
object_points.append(object_point)
img_points.append(corners)
return object_points,img_points
然后使用上方法得到的object_points and img_points 传入cv2.calibrateCamera() 方法中就可以计算出相机校正矩阵(camera calibration matrix)和失真系数(distortion coefficients),再使用 cv2.undistort()方法就可得到校正图片。
def cal_undistort(img, objpoints, imgpoints):
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, img.shape[1::-1], None, None)
dst = cv2.undistort(img, mtx, dist, None, mtx)
return dst
以下为其中一张棋盘格图片校正前后对比:
校正图片测试
#获取棋盘格图片
cal_imgs = utils.get_images_by_dir('camera_cal')
#计算object_points,img_points
object_points,img_points = utils.calibrate(cal_imgs,grid=(9,6))
#获取测试图片
test_imgs = utils.get_images_by_dir('test_images')
#校正测试图片
undistorted = []
for img in test_imgs:
img = utils.cal_undistor