基于透视变换的单目摄像头单一平面障碍物深度信息获取算法

简介

透视变换是一种几何变换,用于将图像从一个视角转换到另一个视角。传统竞速组智能车组别经常使用“逆透视”的思路将摄像头的画面重新透视,以得到赛道的俯视视角。受其启发,本文通过透视变换将位于同一水平面上的障碍物投影到俯瞰视角,以得到其位于摄像机所在平面上的深度信息。

数学说明

透视变换通过一个3x3的变换矩阵实现。矩阵将原图像中的齐次坐标转换为目标图像中的齐次坐标。假设我们有一个点的原始坐标 $(x, y)$,在透视变换后的坐标为 $(x', y')$,则它们的关系可以表示为:

$$ \begin{bmatrix} x' \\ y' \\ \omega \end{bmatrix} = \begin{bmatrix} a_{11} & a_{12} & a_{13} \\ a_{21} & a_{22} & a_{23} \\ a_{31} & a_{32} & a_{33} \end{bmatrix} \begin{bmatrix} x \\ y \\ 1 \end{bmatrix} $$

其中 $(x′,y′)$的实际坐标可以通过归一化得到:$x'=\frac{x'}{\omega}, y'=\frac{y'}{\omega}$。

可以通过给定的点的对应关系来求解这个3x3的透视变换矩阵(其中$a_{33}$为1)。则需要至少4对点的对应关系才能确定唯一的矩阵。每对点关系提供两个独立的方程,因此4对点会提供8个方程,正好可以求出矩阵中的8个独立参数。

定义源和目标点

定义原始图像和输出图像中的四个角点,包括其在图片中的位置和希望得到鸟瞰图中的点位。这些点将用于计算透视变换矩阵。

原始图像的四个角点

mid = 100

# 定义原始图像中四个角的坐标
src_points = np.float32([(247, 306), (568, 305), (291, 258), (435, 257)])

# 定义输出图像中对应的四个角的坐标
dst_points = np.float32([(mid-10, 50), (mid+40, 50), (mid-10, 100), (mid+40, 100)])

src_points定义了原始图像中我们感兴趣的四个角点,而dst_points定义了在输出俯视图中相应的角点位置。

便于后续计算,这里使用的是摄像头物理空间的以cm为单位的实际距离。

计算透视变换矩阵

使用 OpenCV 的getPerspectiveTransform函数计算透视变换矩阵。

matrix = cv2.getPerspectiveTransform(src_points, dst_points)

该矩阵描述了从原图像到俯视图的转换关系。

对图像应用逆透视变换

有了转换矩阵后,我们可以对原图像应用透视变换,将其转换为俯视图。

inversed = cv2.warpPerspective(image, matrix, output_size)

cv2.warpPerspective函数根据给定的变换矩阵将原图像映射到新的视角。这一步的结果是一个新的图像,展示了原图像在俯视视角下的效果。

点的透视变换

需要将俯视图中具体的某个点转换回原图像中的位置,OpenCV没有给出封装好的算法。根据刚刚的数学原理写出以下算法。

此处内容需要评论回复后(审核通过)方可阅读。

这段代码定义了一个函数inverse_perspective_point,它接收变换矩阵和一个点的坐标,返回透视变换后在原图像中的位置。
透视变换后在原图像中的位置

应用示例

在实际应用中,我们可以利用上述技术,将原图中的障碍物位置投影到相对小车的位置上。这将是单目摄像头单一平面特征点视觉SLAM的基础。

富婆饿饿饭饭