人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度学习实战(不定时更新)
CNN:RCNN、SPPNet、Fast RCNN、Faster RCNN、YOLO V1 V2 V3、SSD、FCN、SegNet、U-Net、DeepLab V1 V2 V3、Mask RCNN
车道线检测
相机校正、张氏标定法、极大似然估计/极大似然参数估计、牛顿法、高斯牛顿法、LM算法、sin/cos/tan/cot
相机校正和图像校正:图像去畸变
车道线提取:Sobel边缘提取算法
透视变换
车道线定位及拟合:直方图确定车道线位置
车道曲率和中心点偏离距离计算
在视频中检测车道线
学习目标
根据张正友校正算法,利用棋盘格数据校正对车载相机进行校正,计算其内参矩阵,外参矩阵和畸变系数。
标定的流程是:
标定的图片需要使用棋盘格数据在不同位置、不同角度、不同姿态下拍摄的图片,最少需要3张,当然多多益善,通常是10-20张。该项目中我们使用了20张图片,如下图所示:
把这些图片存放在项目路径中的camera_cal文件夹中。
下面我们对相机进行校正,OPenCV中提供了对相机进行校正的代码,在本项目中直接使用opencv中的API进行相机的校正,如下所示:
# 1. 参数设定:定义棋盘横向和纵向的角点个数并指定校正图像的位置
nx = 9
ny = 6
file_paths = glob.glob("./camera_cal/calibration*.jpg")
# 2. 计算相机的内外参数及畸变系数
def cal_calibrate_params(file_paths):
object_points = [] # 三维空间中的点:3D
image_points = [] # 图像空间中的点:2d
# 2.1 生成真实的交点坐标:类似(0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)的三维点
objp = np.zeros((nx * ny, 3), np.float32)
objp[:, :2] = np.mgrid[0:nx, 0:ny].T.reshape(-1, 2)
# 2.2 检测每幅图像角点坐标
for file_path in file_paths:
img = cv2.imread(file_path)
# 将图像转换为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 自动检测棋盘格内4个棋盘格的角点(2白2黑的交点)
rect, corners = cv2.findChessboardCorners(gray, (nx, ny), None)
# 若检测到角点,则将其存储到object_points和image_points
if rect == True:
object_points.append(objp)
image_points.append(corners)
# 2.3 获取相机参数
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(object_points, image_points, gray.shape[::-1], None, None)
return ret, mtx, dist, rvecs, tvecs
在这里有几个API给大家介绍下:
rect, corners = cv2.findChessboardCorners(image, pattern_size, flags)
参数:
Image: 输入的棋盘图,必须是8位的灰度或者彩色图像
Pattern_size:棋盘图中每行每列的角点个数(内角点)。
flags: 用来定义额外的滤波步骤以有助于寻找棋盘角点。所有的变量都可以单独或者以逻辑或的方式组合使用。取值主要有:
CV_CALIB_CB_ADAPTIVE_THRESH :使用自适应阈值(通过平均图像亮度计算得到)将图像转换为黑白图,而不是一个固定的阈值。
CV_CALIB_CB_NORMALIZE_IMAGE :在利用固定阈值或者自适应的阈值进行二值化之前,先使用cvNormalizeHist来均衡化图像亮度。
CV_CALIB_CB_FILTER_QUADS :使用其他的准则(如轮廓面积,周长,方形形状)来去除在轮廓检测阶段检测到的错误方块。
返回:
rect: 输出是否找到角点,找到角点返回1,否则返回0
检测完角点之后我们可以将将测到的角点绘制在图像上,使用的API是:
cv2.drawChessboardCorners(img, pattern_size, corners, rect)
参数:
注意:如果发现了所有的角点,那么角点将用不同颜色绘制(每行使用单独的颜色绘制),并且把角点以一定顺序用线连接起来,如下图所示:
利用定标的结果计算内外参数
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(object_points, image_points, image_size, None, None)
参数:
返回:
ret: 返回值
mtx: 相机的内参矩阵,大小为3*3的矩阵
dist: 畸变系数,为5*1大小的矢量
rvecs: 旋转变量
tvecs: 平移变量
上一步中我们已经得到相机的内参及畸变系数,我们利用其进行图像的去畸变,最直接的方法就是调用opencv中的函数得到去畸变的图像:
def img_undistort(img, mtx, dist):
dst = cv2.undistort(img, mtx, dist, None, mtx)
return dst
我们看下求畸变的API:
dst = cv2.undistort(img, mtx, dist, None, mtx)
参数:
返回:
总结:
标定的图片
不同角度和方向拍摄的棋盘格图片数据
相机校正
检测棋盘格数据的角点:
cv2.findChessboardCorners()
计算相机的内参数和外参数:cv2.calibrateCamera()
图像去畸变
cv2.undistort()