什么是畸变参数?
畸变参数是一组数学系数,用于描述和校正 VR 头显(如 Google Cardboard)中的图像失真问题。

VR 头显的透镜是凸透镜,光线通过它时会弯曲,导致图像在边缘被拉伸和变形,就像透过一个鱼眼镜头看世界一样,这种失真会严重影响用户的视觉体验,甚至引起眩晕。
畸变参数的作用就是:在图像被发送到屏幕之前,对图像进行“反向预失真”(Pre-distort),当这个预失真的图像再通过透镜时,透镜的物理畸变会将其“拉回”成正确的形状,最终让用户看到清晰、无变形的图像。
为什么需要畸变参数?(透镜的物理原理)
VR 头显中的透镜主要会产生两种畸变:
- 枕形畸变:图像的边缘向内收缩,像一个枕头。
- 桶形畸变:图像的边缘向外扩张,像一个桶。
对于 Cardboard 这样的简单 VR 头显,其透镜主要引入的是桶形畸变,并且这种畸变是径向对称的(以镜头中心为圆心,向各个方向的变化规律相同)。

为了校正这种畸变,我们需要一个数学模型来描述它,这个模型就是由畸变参数定义的。
畸变参数的具体内容(数学模型)
畸变参数通常使用一个多项式函数来描述屏幕上每个像素点 (u, v) 的理想位置 (u', v'),这个函数的核心是计算径向畸变。
核心概念:径向距离
我们需要计算一个像素点到图像中心的径向距离 r,假设图像中心的坐标是 (center_x, center_y),像素坐标是 (u, v),
r = sqrt((u - center_x)² + (v - center_y)²)
畸变函数
理想坐标 (u', v') 的计算公式如下:
u' = u + (u - center_x) * (k1 * r² + k2 * r⁴ + k3 * r⁶ + ...)
v' = v + (v - center_y) * (k1 * r² + k2 * r⁴ + k3 * r⁶ + ...)
这个公式告诉我们:
- 从原始像素坐标
(u, v)出发。 - 计算它到中心的偏移量
(u - center_x)和(v - center_y)。 - 将这个偏移量乘以一个由径向距离
r和畸变系数k组成的畸变因子。 - 将结果加回原始坐标,得到新的、预失真的坐标
(u', v')。
关键参数解析
-
k1, k2, k3 (径向畸变系数 - Radial Distortion Coefficients)
- 这是最核心的畸变参数,它们是一个多项式序列的系数,用于描述畸变随距离
r变化的强度。 - k1:一阶径向畸变系数,影响最大,通常是最主要的畸变来源。
- k2:二阶径向畸变系数,用于校正更高阶的、更复杂的畸变。
- k3:三阶径向畸变系数,对于更精密的镜头系统,用来校正 k2 之后的残余畸变,对于 Cardboard 这样的简单设备,k3 通常为 0 或非常小。
- 符号:
k1为正值,会产生桶形畸变(向外扩张)。k1为负值,会产生枕形畸变(向内收缩)。
- 这是最核心的畸变参数,它们是一个多项式序列的系数,用于描述畸变随距离
-
p1, p2 (切向畸变系数 - Tangential Distortion Coefficients)
- 这两个参数描述的是由于透镜与图像传感器平面不完全平行而产生的切向畸变(也称为“薄棱镜畸变”)。
- 它会导致图像看起来像被“剪切”或倾斜了。
- 对于 Cardboard 这样结构简单、装配精度不高的设备,切向畸变也可能存在,但通常不如径向畸变显著,在许多情况下,为了简化,p1 和 p2 会被设为 0。
-
(cx, cy) (光学中心 - Optical Center)
- 也称为“主点”,是透镜的光学中心在图像传感器(屏幕)上的投影点。
- 它本身不是一个“畸变系数”,但它是计算径向距离
r的基准点,因此是整个畸变校正模型不可或缺的一部分。 - 对于对称的透镜,光学中心通常就是图像的几何中心
(width/2, height/2)。
Cardboard SDK 中的畸变参数
在 Google Cardboard SDK(特别是 C++ 版本)中,这些参数被封装在一个结构体中:
// 在 cardboard/src/distortion_renderer.h 中定义
struct DistortionRenderer::Distortion {
// 径向畸变系数
float k[3];
// 切向畸变系数
float p[2];
// 光学中心
float center[2];
};
如何获取这些参数?
这些参数不是凭空计算的,而是通过校准过程得到的,对于 Cardboard,校准通常由制造商在出厂时完成,或者通过一个配套的 App(如 Cardboard 校准 App)进行。
- 棋盘格标定法:这是计算机视觉中经典的标定方法,用户将手机对准一个打印好的棋盘格图案,从不同角度拍摄多张照片。
- 算法求解:标定软件(如 OpenCV 的
calibrateCamera函数)会分析这些照片,通过优化算法反演出能最好地将棋盘格的“理想世界坐标”映射到“图像像素坐标”的一组相机内参,这组内参就包括了畸变参数k1, k2, k3, p1, p2和光学中心(cx, cy)。
总结与工作流程
| 参数 | 中文名 | 作用 | 在 Cardboard 中的典型值 |
|---|---|---|---|
| k1, k2, k3 | 径向畸变系数 | 描述主要的桶形或枕形畸变,随距离变化。 | k1 是一个明显的正值(如 0.2-0.5),k2, k3 较小或为 0。 |
| p1, p2 | 切向畸变系数 | 描述由透镜倾斜引起的剪切畸变。 | 通常为 0 或接近 0。 |
| (cx, cy) | 光学中心 | 畸变计算的基准点,通常是图像中心。 | (屏幕宽度/2, 屏幕高度/2) |
整个渲染和畸变校正的工作流程如下:
- 渲染左/右眼图像:GPU 渲染出两个独立的、无畸变的、符合双眼视差的图像纹理。
- 应用着色器:GPU 使用一个特殊的顶点着色器。
- 顶点着色器中的计算:对于纹理上的每一个顶点(即屏幕上的每一个像素):
- 获取其原始纹理坐标
(u, v)。 - 根据预存的畸变参数
(k1, k2, k3, p1, p2, cx, cy)和公式,计算出该顶点应该移动到的新纹理坐标(u', v'),这一步就是“预失真”。 - 将这个新的、经过“扭曲”的纹理坐标传递给后续的光栅化阶段。
- 获取其原始纹理坐标
- 显示:这个被“预失真”的图像被绘制到屏幕上,当用户通过 Cardboard 的透镜观察时,透镜的物理畸变恰好抵消了这种数字预失真,从而在视网膜上形成了一个清晰、无变形的立体图像。
希望这个详细的解释能帮助你完全理解 Cardboard 和 VR 中的畸变参数!
