省赛期间用到双目视觉的时候,只是很粗浅地调用了下API,毕竟初学而且时间紧迫。最近打算跟一个硕士生再做一个相关项目,而且也想用Stereo Vision作为毕业设计,所以很有必要了解一下其中的原理。最近也在看《学习OpenCV3》这本书,里面对一些原理的阐述简明易懂,实为神书。虽然不算深入,不过也足够理解算法里面的主要思想了。所以也算是做个读书笔记吧。废话不说,开车!

相机模型
针孔摄像机模型是一种简单而有用的模型,能够一定程度解释光线从物体发射到视网膜或图像采集器的几何过程。其中焦距 f 在针孔摄像机模型中,是指针孔到图像平面的距离(这里指的并不是摄像头中2.0mm,2.5mm这样的表示透镜属性的“焦距”)。Z是物体到投影中心(针孔)的距离,X是物体的长度,x是图像平面上物体的长度。由相似三角形可以得到这样的结论。


真实的针孔由于不能快速曝光收集足够的光线,所以并不是一个得到图像的好办法。这也是为什么眼睛和相机都要使用透镜这样的结构来收集光线。
我们可以简化这个模型。将图像平面放在针孔前面,针孔被理解为投影中心。光轴(Optical axis)与图像平面的较为称为主点(principal point)。这样的话图像的大小不变,而且映射的图像不会反转(回忆一下高中物理和大学物理),公式中的符号去掉了。

当然这是一个很理想的模型。实际上的模型由于工艺的影响,应该写成这样的形式

其中受到了两方面的影响:
-
成像装置(CMOS芯片)的中心通常不在光轴上,所以有了cx和cy两个参数,对投影屏幕坐标中心可能的偏移进行建模
-
透镜物理焦距的偏差,导致像素是矩形的而不是正方形的。fx 实际上是指透镜在x轴上的物理焦距和成像装置每个尺寸单元 sx 的乘积。
射影几何
将物理世界中的坐标映射到投影平面上的点的过程成为“射影变换”。这样可以用齐次坐标来表示投影平面上的二维点。将相机的参数组成一个矩阵,称为“内参矩阵”。于是有以下的形式:


前面讲到,针孔摄像机不能收集到足够的光线。为了能快速地生成图像,我们使用了透镜,让光线弯曲到一个点上,但代价就是带来了畸变。
Rodrigues变换
在三维空间操作时,一般使用旋转矩阵来表示空间的旋转。关于旋转矩阵更多的内容下文会给出。将矩阵乘以一个向量,就相当于将向量以某种方式旋转,但旋转矩阵的缺点就是很难直观理解各个轴旋转的角度。所以Rodrigues提出了以下公式来进行转换,这里不加推导地给出来
设旋转向量为

那么旋转向量到旋转矩阵的变换为

反之则有

透镜畸变
畸变分为两种,径向畸变和切向畸变。径向畸变是指成像装置边缘附近的畸变,远离透镜中心的光纤比透镜中心的光线更加弯曲,如图所示。


对于径向畸变,可以使用光学中心附近(即r=0)的泰勒级数的前几项来描述。一般使用前两项,鱼眼透镜则可以使用三个径向畸变项。


切向畸变则是由于制造上的缺陷使透镜不与成像平面平行而产生的,如图

这里不加推导地给出下面的公式,具体参考“铅锤”模型

旋转矩阵和平移向量
可以用旋转和平移来描述物体相对于相机坐标系统的相对姿态

任何维数的旋转都可以描述为坐标向量和适当尺寸的方阵的乘积。将坐标系统旋转θ相当于将目标点绕原来的坐标轴反方向旋转θ。其中,三维物体的旋转可以分解为围绕每个轴的二维旋转。将三位物体按照某个轴旋转的旋转矩阵如下

那么相乘就有

平移向量用来表示如何将一个坐标系统移动到另一个坐标系统。换句话说,平移向量是第一个坐标系统的远点到第二个坐标系统的偏移量。

那么物体坐标系映射到相机坐标系中的坐标的公式为

标定板
没啥好说的,略

单应性
之前在做全景图像拼接的时候用到过单应矩阵,可以参考这里。单应性定义为从一个平面到另一个平面的投影映射,比如说物体平面到图像平面的映射。如果我们定义

那么定义单应矩阵H为

定义一个这样的矩阵

那么运用一些几何和线代知识,可以知道

看上去可以推出单应矩阵了,但实际上向量Q包含了三维信息,我们只需要它在它的坐标平面上的信息。那么,我们定义一个物体平面,使它Z=0(标定板是一个平面,所以上面的点的Z可以是一样的且为0)。那么可以简化成这样的形式

顺理成章地

那么单应矩阵H可以用这样的方程将图像平面和目标图像平面的点相关联

之前的文章提到,至少要用四个点来求解H。
相机标定
知道如何用数学来描述相机的内在参数和畸变特性之后,接下来一个很自然的问题就是如何使用OpenCV来进行计算。算法的调用可以看我之前写的文章,这里只记录一些原理性的东西。
回顾一下,我们需要求出四个内在参数

五个或更多的畸变参数


OpenCV中的,用于求取焦距和偏移的算法基于Zhang,畸变参数基于Brown。求解过程比较繁琐,懒得说了→_→,网上有篇博客讲的不错。
得到内参矩阵后,可以得到物理坐标到图像坐标的映射关系

得到畸变参数之后,就能对图像进行矫正

理论上只需要两个定位到角点的棋盘图像,但实际上需要10个以上才能得到比较好的结果。
得到这些参数之后,可以用OpenCV中的一些函数得到映射用的矩阵用于矫正
总结
这一章,我们干了这些事情:
-
引入针孔摄像机模型,并引入透镜畸变的概念,建立起数学模型。
-
旋转矩阵和Rodrigues变换。
-
引入了单应性的概念,并用于相机的标定。
下一章我们会讲到双目标定和立体重建的话题。
References:
学习opencv3(中文版) —— Adrian Kaehler & Gary Bradski
三维坐标变换——旋转矩阵与旋转向量
张正友标定算法原理详解
网友评论