智能车传统组常使用“逆透视”的手段获取赛道俯视图,群友将这一思路移植到地平线组,在借鉴学习之后,记录于此。

简介

透视变换(Perspective Transformation) 是一种常见的几何变换,用于处理图像中因视角变化产生的透视效果。基于射影几何,利用单应性矩阵(Homography Matrix,两个平面间的映射关系),通过坐标的线性变换实现从一种透视视角到另一种视角的转换。

数学原理

透视变换使用3×33\times3 的单应性矩阵HH

H=[h11h12h13h21h22h23h31h32h33]H= \begin{bmatrix} h_{11} & h_{12} & h_{13} \\ h_{21} & h_{22} & h_{23} \\ h_{31} & h_{32} & h_{33} \end{bmatrix}

[xyw]=H[xy1]\begin{bmatrix} x^{\prime} \\ y^{\prime} \\ w^{\prime} \end{bmatrix}=H \begin{bmatrix} x \\ y \\ 1 \end{bmatrix}

变换后需要通过归一化操作x=xw,y=ywx' = \frac{x'}{w'}, y^{\prime} = \frac{y^{\prime}}{w^{\prime}}得到实际坐标。

齐次坐标表示二维点

二维欧几里得空间中,一个点表示为[X,Y]T[X,Y]^T,在齐次坐标中表示为[x,y,w]T[x,y,w]^Tww为比例因子,实际坐标为

{X=xwY=yw\begin{cases} X=\frac{x}{w}\\ Y=\frac{y}{w} \end{cases}

w=1w=1时即为常规的二维坐标,透视变换前一般默认w=1w=1,变换后需归一化保持一致性。

为什么要引入齐次坐标?

齐次坐标就是用 N+1 维向量表示 N 维坐标,即用齐次坐标系表示笛卡尔坐标系。引入齐次坐标旨在将各种几何变换都统一成矩阵相乘的形式,比如在二维坐标系中,平移变换只能用矩阵相加的形式表示,而在齐次坐标系中可用矩阵相乘的形式表示。

单应性矩阵求解

由于齐次坐标的比例不变性,即kHkH~HHk0k\ne0,故矩阵只有 8 个自由度,仅需四对变换前后的坐标即可求解单应性矩阵。往往令h33=1h_{33}=1,求得唯一解。

代码实现

选点

需要得到四对或以上点的变换前后坐标

求解单应性矩阵

通过 OpenCV 提供的函数进行求解,cv2.getPerspectiveTransform 由精确的四对点返回单应性矩阵,cv2.findHomography 从四对以上的点中多次取样,通过优化算法筛得最优解,有一定的误差容忍。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import cv2
import numpy as np

# 源点坐标 (四边形)
src_points = np.array([[100, 100], [200, 100], [200, 200], [100, 200]], dtype=np.float32)

# 目标点坐标 (矩形)
dst_points = np.array([[50, 50], [300, 50], [300, 300], [50, 300]], dtype=np.float32)

# 计算单应性矩阵
H, status = cv2.findHomography(src_points, dst_points)

print("单应性矩阵 H:")
print(H)

进行透视变换

1
2
3
4
5
6
7
8
9
10
# 目标图像的尺寸 (宽, 高)
output_size = (300, 200)

# 透视变换
warped_image = cv2.warpPerspective(image, M, output_size)

# 显示结果
cv2.imshow('Warped Image', warped_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

逆透视变换

如果想通过俯视图的坐标得到原图像对应坐标,对单应性矩阵求逆,进行变换即可。


透视变换中的具体应用思路可借鉴(https://hibanaw.com/archives/171/)