行车辅助线生成3-投影到摄像头画面
背景知识
接下来考虑将上部分得到的辅助线绘制到前相机画面中. 首先介绍一些相机内外参的背景知识, 然后才能理解投影操作. 以下大部分内容来自: https://thomasfermi.github.io/Algorithms-for-Automated-Driving/LaneDetection/CameraBasics.html
相机感光元件是一个平面:

放大后如下图:

每个像素由(红, 绿, 蓝)三基色组成:
平面上的每个像素坐标(u, v)如下, 可见相机平面坐标是以左上角为原点的平面直角坐标系:
相机成像是我们熟悉的小孔成像原理:
上图展示了简单的小孔成像, 光线从实物上反射, 穿过相机的针孔, 到达相机底片被光线传感器捕获. 从侧面看是这样的:
上图涉及三个坐标系:
- 物理世界的坐标系, 例如UTM, 表示树的坐标(x, y, z)
- 相机坐标: 以相机针孔为坐标原点的三位坐标系
- 相机平面坐标: 相机感光平面表示的(u, v)坐标系
如果我们想把之前生成的辅助线投影到画面中, 需要: 辅助线坐标 → 相机坐标 → 相机平面坐标. opencv中有现成的方法可供调用cv2.fisheye.projectPoints. 理论知识可以参考:
- https://thomasfermi.github.io/Algorithms-for-Automated-Driving/LaneDetection/CameraBasics.html
- https://docs.opencv.org/4.x/dc/dbb/tutorial_py_calibration.html
- https://docs.opencv.org/3.4/d9/d0c/group__calib3d.html#ga61585db663d9da06b68e70cfbf6a1eac
实现
def projection(left_x, left_y, right_x, right_y, extrinsics, K, D):
"""
将辅助线投影到相机平面
:param left_x: 左线x坐标
:param left_y: 左线y坐标
:param right_x: 右线x坐标
:param right_y: 右线y坐标
:param img: 图片
:param extrinsics: 外参, 世界坐标 -> 相机坐标的转换关系
:param K: 内参, 相机坐标 -> 相机平面的转换关系
:param D: 内参, 鱼眼相机的畸变参数
:return: [左线, 右线]
"""
roll_vel_cam = cv2.decomposeProjectionMatrix(extrinsics)[6][:, 0][0]
pitch_road_cam = roll_vel_cam + 90
rvec = np.float32([-pitch_road_cam / 180 * np.pi, 0, 0])
tvec = np.float32([0, 0, 0])
lines = []
for [x, z] in [[left_x, left_y], [right_x, right_y]]:
y = 1.3879948854446411 # 相机高度, 相机坐标下, y是竖直的
a = np.c_[x, np.repeat(y, len(x)), z]
points_3d = np.expand_dims(a, axis=0)
points_2d, _ = cv2.fisheye.projectPoints(points_3d, rvec, tvec, K, D)
lines.append(points_2d[0])
return lines

至此, 我们就可以根据方向盘转角生成辅助线了.
