欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

这篇文章介绍了摄像机内部和外部参考矩阵的来龙去脉--查看以

最编程 2024-04-07 21:33:54
...

Auther:SeaHIRobot
date: 2023-05-03


最近在做一门课程的项目,在pybullet中复现GGCNN的机械臂视觉抓取的深度学习网络。在搭建仿真环境时,又回到了绕不开的相机内参和外参。借此机会对相机内参外参这一套进行一个review,对这个问题进行一个逻辑梳理。

因此本文不建议纯小白阅读,很多基础概念不会细讲,适合对相机内参外参有一定了解但不完全熟练的同学。

下面的链接是来自pybullet官方Doc中对相机内参的推荐阅读,讲的非常生动。

Dissecting the Camera Matrix, Part 3: The Intrinsic Matrix ←

这里的知乎文章也推荐阅读,内容详细:

zhuanlan.zhihu.com

Problem Defination - 问题定义

我们为什么要研究内参外参呢?这些东西有什么意义呢?

思考一下你目前想干的事情,你有一个相机,你想通过相机来提取场景信息,而通过相机你能获得到的仅仅是由rgb像素构成的2d画面。从3d的世界中,映射出一个2d的画面,这是相机的功能。你想做的,是通过相机输出的2d画面获取3d信息,那么这中间就存在着2d的像素空间和3d的真实空间的一个变换

我们要做的恰恰是寻找这种变换的一种数学表达,借助相机2d的由像素构成的画面,完成我们提取场景信息的任务。

”图片里2d的像素点位 → \rightarrow 3d的世界坐标系中的点位“

这个任务既有3d的坐标变换,又有像素的2d点位向实际的空间坐标之间的尺度变换,怎么进一步拆分好让我们理解呢?那就是一步一步来咯。

”2d像素点位 → \rightarrow 3d相机坐标系点位 → \rightarrow 3d世界坐标系点位“

到这里不熟悉相机坐标系和齐次变换的同学请自行上网百科学习。

Pinhole Camera - 针孔相机

为什么讲针孔相机?这个模型有什么用?

因为他是一个很好理解这个问题的简单的模型,你可以简单得认为所有相机都是这么成像的;

(图源http://ksimek.github.io/2013/08/13/intrinsic)

图中的box就是相机,小孔就是镜头。光路从环境中射入,通过小孔,最终在film上呈现倒像。倒像看起来比较烦,不如我们把按照相似三角形(或着说沿着Pinhole对称一下)到树的一边,就成了正像,如下图。(不用纠结这样做有什么意义,问就是方便看/doge,下面聊内参的时候你将会看到有了操作有多奇妙)

(图源https://zhuanlan.zhihu.com/p/389653208)

使用简单的相似三角形,貌似就可以解决针孔相机的问题。但如果事情再复杂一点呢?

比如:

  • 被拍摄平面(图里的树)和film不是平行的
  • film中心并不在Pinhole轴线上,有垂直轴线平面的偏移
  • 实际的镜头有畸变,不符合针孔摄像头的简单的相似三角形变换
  • blablabla…

下面就有请内参矩阵(intrinsic matrix)登场,进一步刻画这个问题。

Intrinsic Matrix - 内参矩阵

首先,内参矩阵长这个熊样子:
I n t r i n s i c   M a t r i x = ( f x s x 0 0 f y y 0 0 0 1 ) Intrinsic \ Matrix=\left(\begin{array}{c} f_x & s & x_0 \\ 0 & f_y & y_0 \\ 0 & 0 & 1 \end{array}\right) Intrinsic Matrix= fx00sfy0x0y01

先不纠结里面的参数,他干了一件什么事呢?见公式
( u v 1 ) = 1 z c ( f x s x 0 0 f y y 0 0 0 1 ) ( x c y c z c ) \left(\begin{array}{c} u \\ v \\ 1 \end{array}\right) = \frac{1}{z_c}\left(\begin{array}{c} f_x & s & x_0 \\ 0 & f_y & y_0 \\ 0 & 0 & 1 \end{array}\right) \left(\begin{array}{c} x_c \\ y_c \\ z_c \end{array}\right) uv1 =zc1 fx00sfy0x0y01 xcyczc

它连接了像素平面的2d点相机系;

u和v指定了像素平面内的点位,脚标c代表了相机坐标系。 z c z_c zc是相机坐标系的z方向坐标,换一个说法,就是“深度”。前面的 1 z c \frac{1}{z_c} zc1也就是做z方向归一化,也可以把它写进后面的 ( x c , y c , z c ) T (x_c,y_c,z_c)^T (xc,yc,zc)T里,那么相机坐标系里的坐标就变成了在z方向归一化之后的坐标了。下面的图很好的阐释了这个过程,同时也解释了把真实像对称过来的妙处(因为看起来真的舒服)。

(自己画的,凑合看吧)

把上面的式子求个逆,就从像素坐标得到了在相机系中的坐标:
( x c y c z c ) = z c ( f x s x 0 0 f y y 0 0 0 1 ) − 1 ( u v 1 ) \left(\begin{array}{c}x_c \\ y_c \\ z_c \end{array}\right) = {z_c}\left(\begin{array}{c} f_x & s & x_0 \\ 0 & f_y & y_0 \\ 0 & 0 & 1 \end{array}\right)^{-1} \left(\begin{array}{c} u \\ v \\ 1 \end{array}\right) xcyczc =zc fx00sfy0x0y01 1 uv1

那 Intrinsic Matrix 里面的参数是干嘛的呢???为什么x和y方向都有一个焦距???s究竟是什么??? x 0 x_0 x0 y 0 y_0