张正友标定法(相机标定)
这篇博客不会详细介绍张正友相机标定算法的计算过程,所以只是想怎么用openCV或者Matlab实现相机标定的朋友就不用费时间去看了。这篇博客介绍我对张氏标定算法的理解。因为我看到很多资料,觉得很多人对这个算法的理解有问题。虽然我没有用程序实现,但从数学的角度上还是可以分析出来的。
首先推荐一篇博客张正友标定法。这篇博文是我找到的讲解最为详细的,但当中有些论点我仍然觉得有问题。大家可以先看这一篇,理解差不多了在看看我说的是不是有道理。
1.提取多少个角点可以求解方程
2.极大似然估计怎么应用
3.畸变纠正
提取多少个角点可以求解方程
首先我们看一眼要求解的方程
\(s\begin{bmatrix}u\\ v\\ 1\end{bmatrix} = \begin{bmatrix}h_{11} & h_{12} & h_{13}\\ h_{21} & h_{22} & h_{23}\\ h_{31} & h_{32} & h_{33}\end{bmatrix}\begin{bmatrix}X\\ Y\\ 1\end{bmatrix}=H\begin{bmatrix}X\\ Y\\ 1\end{bmatrix}\)
式中:
\(H=A\begin{bmatrix}R & t\end{bmatrix}=\begin{bmatrix}\alpha & \gamma & u_0\\ 0 & \beta & v_0\\ 0 & 0 & 1\end{bmatrix}\begin{bmatrix}r_1 & r_2 & r_3 & t\end{bmatrix}\)
由于,现实坐标是在棋盘板上建立的,默认找到的所有角点,其Z轴坐标都为0,所以省去了一列r3。我们对后一个矩阵继续展开:
\(\begin{bmatrix}r_1 & r_2 & r_3 & t\end{bmatrix}=\begin{bmatrix}r_{11} & r_{12} & r_{13} & t_1\\ r_{21} & r_{22} & r_{23} & t_2\\ r_{31} & r_{32} & r_{33} & t_3\end{bmatrix}\)
我首先说明这个R矩阵是三个分别表示绕x轴,y轴,z轴旋转的单位正交阵相乘的结果,所以每一个列向量和三个旋转方向都是相关的。而不是像别人说,r1与x轴相关,r2与y周相关,r3与z轴相关。由于单位正交阵乘积的结果还是单位正交阵,所以r1,r2,r3是相互正交的单位向量。
注意R和t一共有12个量值,但是R只和三个旋转角度相关,t代表三个方向的偏移量,所以实际上只有6个未知量。而A阵中有5个未知量(如果不考虑x轴与y轴的影响,可以不考虑\(\gamma\)),加起来一共有11个未知量。但最后简化成H阵只有9个变量(虽然删除了r3,但三个旋转角度仍然存在于r1与r2中)。我们还要注意,我么对单眼相机标定的目标不是找到现实世界的坐标和相机像素坐标的关系,准确来讲是要获取相机的内参数。所以我们对棋盘板的位置并不关心。例如我现在有两个大小不同的棋盘版,大的相对小的放的远一点,但保证在相片的中像素坐标是相同的。那么这两个棋盘版计算出来的两个H阵是不同的(棋盘版位置不同),但是是成比例的!这说明H的比例变化是不影响相机的内参数计算的,那么我们干脆将H中的一个变量设定为常数“1”,这样H阵的结果就是唯一的了。此时,这种比例变化就由变量s来平衡,使得方程成立。
我们不妨假定\(h_{33}=1\)。现在只剩下8个变量。其它人都说一个点提供两个方程,所以找4个点就可以了。但是想想就知道,一个平面只有两个线性无关向量,怎么可能提供4个独立无关的点,理论上不是只能提供两个点吗?如果认为只能提供两个点,那么一定忽略的常数项。注意方程:
\(s\begin{bmatrix}u\\ v\\ 1\end{bmatrix} = \begin{bmatrix}h_{11} & h_{12} & h_{13}\\ h_{21} & h_{22} & h_{23}\\ h_{31} & h_{32} & h_{33}\end{bmatrix}\begin{bmatrix}X\\ Y\\ 1\end{bmatrix}=H\begin{bmatrix}X\\ Y\\ 1\end{bmatrix}\)
最后一项是1,而不是0!所以一个平面的基底[1,0]和[0,1],带入方程就变成了[1,0,1]和[0,1,1],这两个向量不能线性表示[0,0,1]。所以实际上一个平面可以提供三个线性无关的点。我们还要注意一个点提供的方程数量是三个,而不是两个(我也不知道别人是怎么得出一个点两个方程的结论)。这样我们从一个棋盘版得到了9个线性无关的方程。可是未知量有8个,方程有9个,不是过约束了?注意,一个棋盘版得到H阵既和内参数相关也和自身位置相关,所以H阵是唯一的!只不过我们知道了H阵的比例变化不影响内参数,才在解出H之后对其做比例变化的。所以实际求解中,忽略s,求解H中的9个参数,再添加s,调整使得\(h_{33}=1\)。
我们求解了H矩阵,得到了9个量值,但是未知量有11个,所以还是不能直接解出内参数矩阵。至于解法,我推荐博文中算法,没有什么问题。
如果我们得到了相机的内参数,那么在以后的坐标转换的问题中就只剩下6个未知量(三个旋转角度和三个平移距离)。逻辑上只需要提供两个点就可以求解这个矩阵。那么是不是以后我们只要输入两个特征点就可以找到坐标转换函数?如果你这样认为,那么你就被我骗了。只要想想就知道,仅凭两个点是不可能确定一个空间坐标系。既然连世界坐标系都确定不了,怎么可能得到坐标转换方程。
并不是我存心要耍你,我只是推理到这一步时才发觉之前的理解有问题。我们所谓的坐标系转换,不是将世界坐标系移动到相机坐标系上,使得两个坐标系重合。如果真能这样,那么深度信息毫无疑问能得到,你都可以移动过来,自然知道两者的距离了。但是这个坐标变换与深度信息毫无关系。这种坐标变换的实质是调整一个坐标系,使得其中元素的表示与元素在另一个坐标系中对应的元素的坐标表示相同。举个例子,现在有坐标系A(相机坐标系)和坐标系B(世界坐标系),我们所做的所有变换是对坐标系B进行平移,旋转,伸缩,使得世界坐标系中的物体在B中坐标表示和对应在相片中的物体在相机中的坐标(由于没有Z,默认两个坐标的Z是相同的),两者的数值相同。由于变换的前后改变的只是坐标系B,而坐标系A和坐标系B的位置关系从头到尾都没有涉及。
其实说到这里,你应该能想到为什么用两个点的对应关系能确定转换矩阵。答案自然是我们少考虑了一些变量——代表三个坐标轴伸缩变换的量
\(K=\begin{bmatrix}k_1\\ k_2\\ k_3\end{bmatrix}\)
如果我们仅用两个点,我们能够确定的是将这两个点对应的直线变换到所对应的直线,实际只需要两个旋转,两个伸缩,两个移动就可以了,所以也刚好有6个独立的方程。但对于完整的坐标变化,我们依然需要9个变量全部知道才可以,也就是我们还是需要知道三个点。
那么之前的推理是否存在问题?我们把伸缩变换添加到方程中:
\(H=KA\begin{bmatrix}R & t\end{bmatrix}=\begin{bmatrix}k_1\\ k_2\\ k_3\end{bmatrix}\begin{bmatrix}\alpha & \gamma & u_0\\ 0 & \beta & v_0\\ 0 & 0 & 1\end{bmatrix}\begin{bmatrix}r_1 & r_2 & r_3 & t\end{bmatrix}\)
我们注意到虽然添加了但H还是9个量,所以对H的求解不影响。至于对相机内参数的求解,你推一下就知道,两个约束方程中也不会出现与K相关的变量,所以A的求解也没有问题。综上,之前的推理不受伸缩变换的影响!但是在坐标系变换的确定中,伸缩变换还是有影响的!所以即使知道了相机的内参数,我们还是需要知道三个点的对应关系才可以求解出转换矩阵!
极大似然估计
我们对一个棋盘板可以得到多个点,但是在求解的过程中我们只会用到三个点。那么选择哪三个点?很简单,遍历所有线性无关的三个点的组合,求解对应的H,并用这个H检验其它点的对应关系是否准确,根据误差计算公式
\(\sum_{n}^{i=1}\sum_{m}^{j=1}\left \| m_{ij}-\hat{m}(H,M_{ij}) \right \|\)
选择误差最小的一组点。
畸变纠正
我对畸变纠正的算法有一个问题。因为畸变在一开始就是存在的,但是在计算坐标转换时默认是不考虑的。那么我们计算的坐标转换就是不准确的,怎么可以应用到畸变纠正中,并期望得到正确的结果?实际这就是一个鸡生蛋还是蛋生鸡的问题。对于这种问题常用的求解算法就是迭代求解。我们可以选取视觉中心的三个点求解H,尽可能减少畸变的影响,再去求解畸变参数。有了畸变参数再去纠正图像,再去计算转换矩阵H,反复几次应该就可以减小误差。实际上在最大似然估计的过程中,大概率选择的三个点就是中心的三个点。