计算机视觉(四)
前面的章节讲的都是图像到图像之间的映射和变换。为了处理三维图像和平面图像之间的映射,我们需要在映射中加入部分照相机产生图像过程的投影特性。这一章就是关于确定照相机的参数求解等。
针孔相机模型

图像点 p 是由图像平面与连接三维点 P和照相机中心 C 的直线相交而成的。z轴表示该照相机的光学坐标轴,由此可以得出针孔照相机的投影性质。照相机的光学坐标轴和 z 轴一致,该投影几何可以简化成相似三角形。在针孔照相机中,三维点 P 投影为图像点 p 两个点都是用齐次坐标表示的),如下所示:

照相机矩阵
其中的照相机矩阵可以进一步分解成:

内标定矩阵 K 描述照相机的投影性质,也就是内参矩阵,该矩阵仅与照相机自身情况相关,通常是以如下方式表示:

图像平面和照相机中心间的距离为焦距 f。当像素数组在传感器上偏斜的时候,需要用到倾斜参数 s。在大多数情况下,s 可以设置成 0。纵横比例参数 α 是在像素元素非正方形的情况下使用的,比如说畸变现象:径向畸变、桶状畸变、枕形畸变等。通常情况下, α默认设置为1。除焦距之外,标定矩阵中剩余的唯一参数为光心(有时称主点)的坐标 [Cx,Cy]也就是光线坐标轴和图像平面的交点。在这个例子中,唯一未知的变量是焦距 f。
另外还有相机的外参矩阵:

其中,R 是描述照相机方向的旋转矩阵,t 是描述照相机中心位置的三维平移向量。以上就是我们的主要求解的两类参数。
相机标定
照相机矩阵的分解
在已经获取到相机矩阵的情况下,我们可以逆向恢复内参数 K 以及照相机的位置 t 和姿势 R。矩阵分块操作称为因子分解。这里,我们将使用一种矩阵因子分解的方法,称为 RQ 因子分解。
def factor(self): """ 将相机矩阵分解成K、R、T """ # 分解前 3*3 的部分 K,R = linalg.rq(self.P[:,:3]) # 将 K 的对角线元素设为正值 T = diag(sign(diag(K))) if linalg.det(T) < 0: T[1,1] *= -1 self.K = dot(K,T) self.R = dot(T,R) # T 的逆矩阵为其自身 self.t = dot(linalg.inv(self.K),self.P[:,3]) return self.K, self.R, self.t
在该因子分解中,分解的结果存在符号二义性,所以RQ 因子分解的结果并不是唯一的,但我们可以在结果中加入变换 T 来改变符号,这样就可以达到限制旋转矩阵 R 为正定的效果。

在已经获取到相机矩阵的情况下,我们还可以计算出空间上照相机的所在位置。照相机的中心C,照相机的中心和内标定矩阵 K 无关,是一个三维点,可以由下式:

def center(self): """ Compute and return the camera center. """ if self.c is not None: return self.c else: # compute c by factoring self.factor() self.c = -dot(self.R.T,self.t) return self.c
标定照相机是指计算出该照相机的内参数,即上面提到的计算矩阵 K。标定照相机的标准方法是,拍摄多幅平面棋盘模式的图像,然后进行处理计算。
具体实验步骤
- 打印一张棋盘格A4纸张(黑白间距已知)贴在一个平板上
- 针对棋盘格拍摄若干张图片 (一般10-20张)
- 在图片中检测特征点 (Harris角点)
- 根据角点位置信息及图像中的坐标,求解Homographic矩阵
- 利用解析解估算方法计算出5个内部参数,以区6个外部参数
- 根据极大似然估计策略,设计优化目标并实现参数的refinement
该实验方法仅需要平面标定板,拍摄若干张图片,标定板中的模式也十分灵活,可以是棋盘格,也可以是其他几何结构已知的图形,实验结果表明具有很好的标定精度,具有很强的灵活性 。
Harris角点检测我们在前面就实践过了,而求解Homographic矩阵,就是我们常见的根据已知求解一个未知矩阵
其中的就包括了我们要求的参数H,可以根据角点世界坐标到图像坐标的关系通过最小二乘法来求解。
利用解析解估算方法计算出5个内部参数,以区6个外部参数


当观测平面n≥3时,可以得到b的唯一解;当n=2时,一般可令畸变参数y=0;当n=1时,仅能估算出alpha与beta,此时一般可假定像主点坐标为[0,0]。这就是为什么一开始我们需要拍10到20张图片的原因。
最后就是优化我们求出的参数,计算重投影误差,重投影误差指空间中某个3D点通过估计的相机位姿重投影得到的像素点,与实际拍摄图像中的像素点之间的误差(欧氏距离)。它可以用来衡量标定的精度,通过重投影误差可以衡量标定的好坏,那么我们的目标可以是最小化重投影误差,也就是最小化下述公式:
具体标定计算,opencv里有集成的代码,也可以借助matlab
matlab求解内外参数
简单地导入图片运行就可以得到结果:



很明显,选择移动相机固定棋盘格还是固定相机移动棋盘格对参数的求解是没有影响的,我是进行移动相机固定棋盘格,但matlab还可以模拟出相对的固定相机移动棋盘格。

随着图像的增加,误差逐渐减小,并趋于平稳,总体平均误差为0.33。

导出参数,框出的部分分别是世界坐标,平移矩阵,相机内参,图像坐标,旋转矩阵。其中相机内参是多张图片求解得到唯一确定的,而平移矩阵和旋转矩阵作为外部参数是针对每张图片各个求解的。

上图为内参矩阵,这个与程序中的是转置关系。


上两图是平移矩阵和旋转矩阵,因为每张图片对应一个世界坐标系,旋转矩阵和平移矩阵是世界坐标系相对于摄像机坐标系的,而算法中规定世界坐标系是标定板为z=0的平面,对于不同位置拍摄的图片,其世界坐标系的定义是不同的,这也就不难解释为什么有多个旋转矩阵和平移矩阵了。