摄像机矩阵
前言
最近翻阅关于从2D视频或者图片中重构3D姿态的文章及其源码,发现都有关于摄像机参数的求解,查找了相关资料,做一下笔记。
国际惯例,来一波参考网址
透视变换、透镜畸变及校正模型、相机校正(Camera Calibration)、Matlab相机校正工具箱、【立体视觉(一)】由基本矩阵、本质矩阵恢复摄像机矩阵——Structure from motion、Multiple View Geometry in Computer Vision(计算机视觉中的多视角几何),附matlab代码 、相机矩阵的分解系列教程、摄像机矩阵详解(中文版)
【注】本文主要提取倒数第二个大牛博客的主要内容,最后一个博客是某位国内大神对这位大牛博客的精解,其它部分为图像知识的补充,主要来源于《OpenGL编程指南》第五章节。博客不在于深究各种细节实现,主要在于对此知识点有所了解,也就是看大牛们的代码的时候至少要知道我们需要求解的东西是什么,都包含什么参数。对理论没兴趣的可以直接看总结,也可看demo展示.
基本知识复习
相机模型
先看看使用相机的主要步骤:
- 移动相机到拍摄位置,镜头对准某个方向(视图变换,view transform)
- 将拍摄对象一到场景中的某个位置(模型变换,model transform)
- 设置相机焦距或调整缩放比例(投影变换,projection transform)
- 对结果图像拉伸或者压缩,变换为需要的图片大小(视口变换,viewpoint transform)
其中前两步可以合并为一个步骤,称为模型-视图变换(model-view transform),包含多级平移、旋转、缩放。下图摘自OpenGL一书,用于理解对象从一个坐标系统到另一个坐标系统的变换过程
齐次坐标
先看看矩阵乘法在三维坐标变换的缺点:将三维坐标视为一个列向量,那么矩阵*列向量得到的新向量的每一个分量,都是旧的列向量的线性函数,因而三维笛卡尔坐标与矩阵的乘法只能实现三维坐标的缩放和旋转,而无法实现坐标平移。
[ 1 0 0 0 0 2 0 1 0 ] [ x y z ] = [ x 2 z y ] \begin{bmatrix} 1&0&0\\ 0&0&2\\ 0&1&0 \end{bmatrix} \begin{bmatrix} x\\y\\z \end{bmatrix}= \begin{bmatrix} x\\2z\\y \end{bmatrix} ⎣⎡100001020⎦⎤⎣⎡xyz⎦⎤=⎣⎡x2zy⎦⎤
[ 1 0 0 0 0 0 2 0 0 1 0 3 0 0 0 1 ] [ x y z 1 ] = [ x 2 z y + 3 1 ] \begin{bmatrix} 1&0&0&0\\ 0&0&2&0\\ 0&1&0&3\\ 0&0&0&1 \end{bmatrix} \begin{bmatrix} x\\y\\z\\1 \end{bmatrix}= \begin{bmatrix} x\\2z\\y+3\\1 \end{bmatrix} ⎣⎢⎢⎡1000001002000031⎦⎥⎥⎤⎣⎢⎢⎡xyz1⎦⎥⎥⎤=⎣⎢⎢⎡x2zy+31⎦⎥⎥⎤
可以发现将三维的笛卡尔坐标添加一个额外坐标,就可以实现坐标平移了,而且保持了三维向量与矩阵乘法具有的缩放和旋转操作。这个就称为齐次坐标。而这种变换也称为仿射变换(affine transformation),不属于线性变换(线性变换的一个重要规则就是 ( 0 , 0 , 0 ) (0,0,0) (0,0,0)映射以后仍是 ( 0 , 0 , 0 ) (0,0,0) (0,0,0))。
齐次坐标的好处也就显而易见了:
- 进一步完成透视变换,也可戳这里,其实第四个分量就是用于实现透视投影变换的,所有的分量同时处理相同值不会改变它所表达的位置。
- 使用线性变换完成模型的平移
【注意】我们经常将第四个分量记为 w w w,OpenGL会在显示几何体的时候用前三个分量除以第四个分量,从而将齐次坐标变换为笛卡尔坐标。当 w = 0.0 w=0.0 w=0.0的时候,表示物体位于无限近的位置,透视效果就是无限大的,所以会产生一些无法预知的结果。而且当 w w w是负数的时候,虽然理论可以,但是负数 w w w值可能会给图形管线的某些环节带来麻烦,当与其它的正数 w w w进行计插值计算的时候,导致结果接近或等于0。避免这个问题的方法就是保证第四个分量 w w w为正。
相机矩阵内参和外参的分解
相机矩阵
-
何为几何相机校正(Geometric camera calibration) ?
也称为相机反切(camera resectioning),主要用于估计图像或者视频摄像机的透镜和图像传感器的相关参数。使用这些参数可以纠正透镜畸变,度量真实世界中物体的大小,或者相机在一个场景中的定位。因而可以被用于机器视觉,去检测或者度量事物,也可用于机器人中,帮助导航系统和3D重建。
-
相机参数都有哪些?估计它们需要的条件?评估所估算的相机参数好坏的标准?
①主要包含内参(intrinsics)、外参(extrinsics)、畸变系数(distortion coefficients)
②估计参数需要3D世界坐标及其对应的2D图像点。比如在重构3D姿态的时候,需要同时输入图片及图片中对应的人的骨骼2D坐标点。
③评估所估计相机参数的方法就是:首先画出相机和校准模式的相对位置;随后计算投影误差;最后计算参数的估算误差。在matlab中有Camera Calibrator来进行相机校准和评估参数精确度。
何为几何相机校正(Geometric camera calibration) ?
也称为相机反切(camera resectioning),主要用于估计图像或者视频摄像机的透镜和图像传感器的相关参数。使用这些参数可以纠正透镜畸变,度量真实世界中物体的大小,或者相机在一个场景中的定位。因而可以被用于机器视觉,去检测或者度量事物,也可用于机器人中,帮助导航系统和3D重建。
相机参数都有哪些?估计它们需要的条件?评估所估算的相机参数好坏的标准?
①主要包含内参(intrinsics)、外参(extrinsics)、畸变系数(distortion coefficients)
②估计参数需要3D世界坐标及其对应的2D图像点。比如在重构3D姿态的时候,需要同时输入图片及图片中对应的人的骨骼2D坐标点。
③评估所估计相机参数的方法就是:首先画出相机和校准模式的相对位置;随后计算投影误差;最后计算参数的估算误差。在matlab中有Camera Calibrator来进行相机校准和评估参数精确度。
图片代码来源:戳这里1、戳这里2
-
相机矩阵的表示?缺点?
假设有一个 3 ∗ 4 3*4 3∗4的相机矩阵,可以将齐次3D坐标转换为2D图像坐标。矩阵表示如下
P = [ M ∣ − M C ] P=[M|-MC] P=[M∣−MC]
这里的’ ∣ | ∣'代表的是增广矩阵。其中 M M M代表可逆的 3 ∗ 3 3*3 3∗3矩阵, C C C是列向量,代表世界坐标系中相机位置。相机矩阵可以将3D点投影到2D空间,但是有些缺点:
-
没有提供相机的摆放姿态
-
没有提供相机的内部几何特征
-
不能使用镜面光照,因为无法在相机坐标系中得到表面法线向量。
-
相机矩阵分解
为了解决上述问题,可以将相机矩阵分解为两个矩阵的乘积:内参矩阵 K K K和外参矩阵 [ R ∣ − R C ] [R|-RC] [R∣−RC]
P = K [ R ∣ − R C ] P=K[R|-RC] P=K[R∣−RC]
其中, 3 ∗ 3 3*3 3∗3的上三角阵 K K K描述了相机的内参比如焦距; 3 ∗ 3 3*3 3∗3的旋转矩阵 R R R的列表示相机参考帧的世界坐标轴方向;向量 C C C是世界坐标系中的相机中心。那么向量 t = − R C t=-RC t=−RC就给出了相机坐标系中的世界原点位置。我们需要做的就是求解这些参数,当然前提是我们已经知道 P P P了。
相机中心
相机中心的求解比较简单,利用分解前的相机矩阵,由于 P P P的最后一列是由 − M C -MC −MC得到的,而 M M M在原始的相机矩阵的前 3 ∗ 3 3*3 3∗3部分已经给出了,所以只需要用 − M − 1 -M^{-1} −M−1左乘它即可。
旋转矩阵和内参
首先注意旋转矩阵R是正交的,因为每一列代表的是一个轴(想想三维坐标系的xyz轴是不是垂直的);而内参矩阵 K K K是一个上三角阵。然后考虑到 Q R QR QR分解的用途就是将一个满秩矩阵分解为上三角阵和正交阵的乘积。算法好像不难,matlab的写法如下
function [R Q] = rq(M)
[Q,R] = qr(flipud(M)')
R = flipud(R');
R = fliplr(R);
Q = Q';
Q = flipud(Q);
但是发现 Q R QR QR分解的结果不唯一,对 K K K的任何一列以及 R R R的对应行取反(negative)都不会导致相机矩阵结果的改变。
如果满足如下两个条件,可以让 K K K的对角元为正
- 图像的X/Y轴所指方向与相机的X/Y轴方向相同
- 相机处于z轴正方向
所以可以取QR分解中,使得 K K K的对角元为正的解,让 K K K对角元为正的代码如下
# make diagonal of K positive
T = diag(sign(diag(K)));
K = K * T;
R = T * R; # (T is its own inverse)
然而在实际中,照相机和图片的轴经常不统一,所以 K K K的对角元也不应该是正的,如果强制它们为正,将会导致一些不好的副作用,包含:
- 对象位于相机错误的一边
- 旋转矩阵行列式为 − 1 -1 −1而不是 1 1 1
- 不正确的镜面光照( specular lighting)
- 出现视觉几何无法被渲染问题,原因在于具有负的w坐标
如果从全正的对角元开始,你需要做的就是:
- 如果图像x轴和摄像机x轴指向相反方向,将 K K K的第一列以及 R R R的第一行取反
- 如果图像y轴和摄像机y轴指向相反方向,将 K K K的第二列以及 R R R的第二行取反
- 如果相机俯视是z轴负方向,将 K K K的第三列以及 R R R的第三行取反。
- 如果 R R R的行列式置为 − 1 -1 −1,将它取反
以上每一步都能保证相机矩阵不变,最后一步等价于将整个相机矩阵 P P P乘以 − 1 -1 −1。因为 P P P的操作是基于齐次坐标系的,所以将它乘以任何的常量都无影响。
当然可以使用向量 t = − R C t=-RC t=−RC去检查结果,此式代表的是在相机坐标系中的世界坐标系原点。如果都没错,那么 t x , t y , t z t_x,t_y,t_z tx,ty,tz应该能够反映出在世界原点在相机中的位置(分别指出在中心左边/右边,上边/下边,相机的前面/后面)
相机矩阵求解
前面看了如何将相机矩阵分解为内参和外参矩阵的乘积。
外参矩阵
相机的外参矩阵描述的是世界坐标中相机的位置,及其指向方向。有两个成分:旋转矩阵 R R R和平移向量 t t t。它们并非恰好对应相机的旋转和平移。
外参矩阵以刚体变换矩阵的形式可以记为:左边一个 3 ∗ 3 3*3 3∗3旋转矩阵,右边一个 3 ∗ 1 3*1 3∗1的平移列向量
上一篇:
点云数据集和点云制图
[ R ∣ t ] = [ r 1 , 1 r 1 , 2 r 1 , 3 ∣ t 1 r 2 , 1 r 2 , 2 r 2 , 3 ∣ t 2 r 3 , 1 r 3 , 2 r 3 , 3 ∣ t 3 ] [R|t]=\begin{bmatrix} r_{1,1}&r_{1,2}&r_{1,3}&|&t_1\\ r_{2,1}&r_{2,2}&r_{2,3}&|&t_2\\ r_{3,1}&r_{3,2}&r_{3,3}&|&t_3 \end{bmatrix} [R∣t]=⎣⎡r1,1r2,1r3,1r1,2r2,2