内参标定

一、内参标定

相机内参主要标定相机的内参与畸变参数

给标定板建立坐标系,建立归一化平面与标定板坐标系的转换关系。

归一化平面是指相机坐标系下 Z = 1 时的平面。

归一化平面上的点为:

(x, y, 1)

相机内参矩阵 K 为一个 3×3 矩阵:

fx   0   Cx
0    fy  Cy
0    0   1

其中:

  • fx:X方向上的焦距,单位为像素
  • fy:Y方向上的焦距,单位为像素
  • Cx:相机主点在图像上的X坐标
  • Cy:相机主点在图像上的Y坐标

那么归一化平面坐标 (x, y) 与像素坐标 (u, v) 可以建立关系:

u = fx * x + Cx
v = fy * y + Cy

其中:

  • (x, y) 是归一化平面坐标
  • (u, v) 是图像上的像素坐标

设标定板坐标系下的某个点为:

(Xw, Yw, Zw, 1)

那么可以建立完整的投影关系:

s * (u, v, 1)T = K * [R, T] * (Xw, Yw, Zw, 1)T

其中:

  • K:相机内参
  • R:标定板坐标系到相机坐标系的旋转矩阵
  • T:标定板坐标系到相机坐标系的平移向量
  • s:齐次坐标的比例系数

将旋转矩阵写成:

R = (r1, r2, r3)

因为标定板是一个平面,所以可以直接把标定板坐标系建立在标定板平面上。

此时标定板上的所有角点都有:

Zw = 0

因此:

s * (u, v, 1)T
=
K * [r1, r2, r3, T] * (Xw, Yw, 0, 1)T

因为 Zw = 0,所以 r3 对应的这一项永远乘以0,因此可以删除。

得到:

s * (u, v, 1)T
=
K * [r1, r2, T] * (Xw, Yw, 1)T

定义:

H = K * [r1, r2, T]

于是:

s * (u, v, 1)T
=
H * (Xw, Yw, 1)T

这个 H 就叫做单应矩阵 Homography


二、先求每一张标定图片的单应矩阵H

H 写成:

H =
h11 h12 h13
h21 h22 h23
h31 h32 h33

那么:

s * (u, v, 1)T
=
H * (Xw, Yw, 1)T

展开得到:

s*u = h11*Xw + h12*Yw + h13

s*v = h21*Xw + h22*Yw + h23

s   = h31*Xw + h32*Yw + h33

把第三个公式:

s = h31*Xw + h32*Yw + h33

代入前面的两个公式。

可以得到:

u =
(h11*Xw + h12*Yw + h13)
/
(h31*Xw + h32*Yw + h33)

以及:

v =
(h21*Xw + h22*Yw + h23)
/
(h31*Xw + h32*Yw + h33)

将分母移到等式左边:

u*(h31*Xw + h32*Yw + h33)
=
h11*Xw + h12*Yw + h13
v*(h31*Xw + h32*Yw + h33)
=
h21*Xw + h22*Yw + h23

整理以后:

Xw*h11 + Yw*h12 + h13
-u*Xw*h31 - u*Yw*h32 - u*h33
= 0
Xw*h21 + Yw*h22 + h23
-v*Xw*h31 - v*Yw*h32 - v*h33
= 0

因此,一个标定板角点可以提供两个方程

也就是说,只要我们知道:

标定板真实坐标 (Xw, Yw)

以及:

这个角点在图片中的像素坐标 (u, v)

就可以建立两个关于 H 的方程。


三、为什么可以求出H

H 一共有9个参数:

h11
h12
h13

h21
h22
h23

h31
h32
h33

但是单应矩阵是一个齐次矩阵。

例如:

H

和:

2H

所表达的投影关系是一样的。

因此 H 实际只有8个独立自由度

一个角点能够提供两个方程。

所以理论上:

4个不共线的角点

就可以提供:

4 × 2 = 8

个约束,从而求出单应矩阵 H

实际标定时,一个棋盘格一般会有几十个角点。

例如:

标定板坐标              图像像素坐标

(0, 0)        ->       (523.2, 314.5)

(20, 0)       ->       (557.8, 312.1)

(40, 0)       ->       (592.1, 309.8)

...

这些点全部参与计算。

由于实际角点检测存在误差,所以一般不会只使用4个点,而是使用所有角点,通过最小二乘或者SVD求一个最合理的 H

第一张图片得到:

H1

第二张图片得到:

H2

第三张图片得到:

H3

最终得到:

H1
H2
H3
...
Hn

四、通过H计算相机内参K

前面已经知道:

H = K * [r1, r2, T]

H 按照列拆开:

H = (h1, h2, h3)

于是存在:

h1 = λ * K * r1

h2 = λ * K * r2

h3 = λ * K * T

其中 λ 是比例系数。

那么:

r1 = (1/λ) * K^-1 * h1

r2 = (1/λ) * K^-1 * h2

这里有一个非常关键的信息:

r1r2 是旋转矩阵 R 的前两列。

而旋转矩阵的每一列其实都是一个单位坐标轴。

所以它们满足两个重要性质。

1. r1和r2互相垂直

因此:

r1T * r2 = 0

2. r1和r2长度相同

因为它们都是单位向量,所以:

r1T * r1 = r2T * r2 = 1

因此:

r1T * r1 = r2T * r2

这两个条件就是后面求相机内参的关键。


五、利用旋转矩阵的性质求K

因为:

r1 = (1/λ) * K^-1 * h1
r2 = (1/λ) * K^-1 * h2

根据:

r1T * r2 = 0

代入得到:

h1T * K^-T * K^-1 * h2 = 0

再根据:

r1T * r1 = r2T * r2

可以得到:

h1T * K^-T * K^-1 * h1
=
h2T * K^-T * K^-1 * h2

为了让公式简单一点,定义:

B = K^-T * K^-1

那么上面的两个公式就变成:

h1T * B * h2 = 0

以及:

h1T * B * h1
-
h2T * B * h2
=
0

所以:

每一张标定板图片,都可以利用自己的单应矩阵 H 提供两个关于相机内参的约束。


六、B矩阵是什么

因为:

B = K^-T * K^-1

所以 B 是一个对称矩阵。

可以写成:

B11 B12 B13
B12 B22 B23
B13 B23 B33

因此它只有6个不同的未知数:

B11
B12
B22
B13
B23
B33

把它们写成一个向量:

b =
(B11,
 B12,
 B22,
 B13,
 B23,
 B33)T

每张标定图片可以提供两个约束。

假设拍摄了很多张不同角度的标定图片,就可以得到很多方程。

最后组合成:

V * b = 0

然后通过SVD计算出:

b

从而得到矩阵:

B

七、通过B恢复内参K

因为已经知道:

B = K^-T * K^-1

而内参矩阵为:

fx   0   Cx
0    fy  Cy
0    0   1

所以可以通过 B 反推出:

fx
fy
Cx
Cy

最终得到:

K =
fx   0   Cx
0    fy  Cy
0    0   1

如果考虑像素坐标轴之间不完全垂直,还存在一个 skew 参数:

K =
fx   skew  Cx
0    fy    Cy
0    0     1

但是现代工业相机通常认为:

skew = 0

所以平时看到的基本都是:

fx   0   Cx
0    fy  Cy
0    0   1

到这里,已经得到了相机内参的初始值


八、为什么还要计算每张图片的R和T

前面:

H = K * [r1, r2, T]

现在 K 已经知道了,所以可以反过来计算每张标定图片对应的外参。

根据:

h1 = λ * K * r1

可以得到:

r1 = λ * K^-1 * h1

同理:

r2 = λ * K^-1 * h2

以及:

T = λ * K^-1 * h3

比例系数 λ 可以通过下面的关系计算:

λ = 1 / ||K^-1 * h1||

求出 r1r2 后:

r3 = r1 × r2

于是得到:

R = [r1, r2, r3]

最终每一张图片都可以得到一套:

R
T

需要注意:

同一个相机的内参K是不变的。

但是每一张标定图片的:

R
T

是不一样的。

因为拍照的时候,标定板相对于相机的位置和姿态一直在变化。

例如:

第1张图片:

R1
T1
第2张图片:

R2
T2
第3张图片:

R3
T3

而所有图片共享同一个:

K

九、为什么还要计算畸变

前面使用的模型:

u = fx*x + Cx

v = fy*y + Cy

是一个理想针孔相机模型

但是实际相机里面有镜头。

真实镜头并不是完全理想的,所以图像会发生畸变。

例如原本应该是一条直线:

-------------------------

可能拍出来变成:

----_____________----

或者:

____-------------____

因此只计算:

fx
fy
Cx
Cy

还不够。

还需要计算镜头的畸变参数。

常见畸变主要分为:

  1. 径向畸变
  2. 切向畸变

十、径向畸变

假设理想归一化平面坐标为:

(x, y)

先计算这个点距离归一化平面中心的距离:

r² = x² + y²

考虑径向畸变以后:

xd =
x * (1 + k1*r² + k2*r⁴ + k3*r⁶)
yd =
y * (1 + k1*r² + k2*r⁴ + k3*r⁶)

其中:

k1
k2
k3

就是径向畸变参数。

径向畸变最大的特点就是:

距离图像中心越远,畸变通常越明显。

常见的桶形畸变、枕形畸变,主要就是径向畸变。


十一、切向畸变

如果镜头和相机内部的成像平面没有做到完全平行,还会产生切向畸变。

切向畸变通常使用:

p1
p2

描述。

公式为:

xd =
x
+ 2*p1*x*y
+ p2*(r² + 2*x²)
yd =
y
+ p1*(r² + 2*y²)
+ 2*p2*x*y

十二、径向畸变和切向畸变合在一起

实际计算的时候,通常会把两种畸变一起计算。

得到:

xd =
x*(1 + k1*r² + k2*r⁴ + k3*r⁶)
+ 2*p1*x*y
+ p2*(r² + 2*x²)
yd =
y*(1 + k1*r² + k2*r⁴ + k3*r⁶)
+ p1*(r² + 2*y²)
+ 2*p2*x*y

得到畸变后的归一化坐标:

(xd, yd)

再通过相机内参转成像素:

u = fx*xd + Cx

v = fy*yd + Cy

所以OpenCV中常见的5个畸变参数就是:

k1
k2
p1
p2
k3

十三、畸变参数到底是怎么算出来的

现在我们已经知道:

  • 标定板角点真实坐标
  • 每个角点真实拍摄到的像素坐标
  • 初步计算出来的相机内参K
  • 每张图片对应的R和T

假设标定板中一个角点为:

Pw = (Xw, Yw, Zw)

首先通过当前图片对应的外参:

Pc = R * Pw + T

得到这个点在相机坐标系中的坐标:

Pc = (Xc, Yc, Zc)

然后投影到归一化平面:

x = Xc / Zc

y = Yc / Zc

然后加入当前的畸变参数:

(x, y)
    ↓
畸变模型
    ↓
(xd, yd)

然后通过内参得到预测像素:

u' = fx*xd + Cx

v' = fy*yd + Cy

也就是说,根据当前相机参数,我们预测这个角点应该出现在:

(u', v')

但是实际图片检测出来的位置可能是:

(u, v)

那么二者之间就存在误差:

du = u - u'

dv = v - v'

这个点的误差大小为:

e = sqrt(du² + dv²)

这个就是重投影误差


十四、为什么叫重投影误差

因为整个过程实际上是:

已知标定板3D坐标
        ↓
      R、T
        ↓
相机坐标系3D坐标
        ↓
      / Z
        ↓
  归一化平面坐标
        ↓
     畸变模型
        ↓
       K
        ↓
   预测像素坐标

然后拿这个预测出来的像素坐标,和真实图片里面检测到的像素坐标进行比较。

相当于:

把标定板上的三维点重新投影回图片上。

所以叫:

Reprojection Error,重投影误差。


十五、最终不是只计算一次,而是整体优化

前面通过单应矩阵计算出来的:

fx
fy
Cx
Cy

以及:

R
T

主要是为了得到一个比较好的初始值

最终标定还需要做非线性优化。

优化变量包括:

fx
fy
Cx
Cy

k1
k2
k3
p1
p2

第1张图片的 R1、T1
第2张图片的 R2、T2
第3张图片的 R3、T3
...

然后计算所有图片、所有角点的重投影误差。

目标就是:

让所有角点的预测像素
尽可能接近
真实检测出来的像素

也就是最小化:

Σ Σ || 实际像素 - 预测像素 ||²

不断调整:

K
畸变参数
每张图片的R、T

让整体误差越来越小。

最后得到最优的:

fx
fy
Cx
Cy

k1
k2
p1
p2
k3

这就是最终保存下来的相机标定参数。


十六、内参标定完整流程

整个内参标定过程可以总结成:

已知标定板尺寸
        ↓
建立标定板坐标系
        ↓
得到角点真实坐标 (Xw, Yw, 0)
        ↓
拍摄多张不同姿态的标定板图片
        ↓
检测图片角点 (u, v)
        ↓
建立:
(Xw, Yw) <-> (u, v)
对应关系
        ↓
每张图片计算单应矩阵 H
        ↓
利用旋转矩阵正交约束
计算相机内参 K
        ↓
计算每张图片对应的 R、T
        ↓
加入镜头畸变模型
        ↓
计算重投影误差
        ↓
对 K、畸变、R、T 进行整体非线性优化
        ↓
得到最终标定结果

最终得到:

相机内参:

fx
fy
Cx
Cy

以及:

畸变参数:

k1
k2
p1
p2
k3

十七、一句话理解内参标定

内参标定本质上就是:

我知道标定板上的一个点在真实世界中的位置,也知道这个点最终拍到了图片的哪个像素,通过大量这样的对应关系,反推出这个相机到底是如何完成“3D世界 -> 2D图像”这个投影过程的。

最终得到两类参数:

K:描述理想针孔相机模型

D:描述真实镜头产生的畸变

也就是:

真实3D点
    ↓
外参 R、T
    ↓
相机坐标
    ↓
透视投影
    ↓
归一化坐标
    ↓
畸变
    ↓
相机内参 K
    ↓
像素坐标

然后通过不断减小预测像素和实际像素之间的重投影误差,最终得到最符合真实相机的内参与畸变参数。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容