OpenCV(Python)的基本矩阵和本质矩阵不一致

4

我尝试使用OpenCV(Python接口)对立体相机进行校准。我首先使用calibrateCamera2分别对两个相机进行了校准,然后将参数输入到stereoCalibrate中。

cv.StereoCalibrate(object_points, image_points_left, image_points_right, \
               point_counts, intrinsic_left, distortion_left,\
               intrinsic_right, distortion_right, \
               (IMGRES_X,IMGRES_Y), R, T, E, F, \
               term_crit=(cv.CV_TERMCRIT_ITER+cv.CV_TERMCRIT_EPS, 100, 1e-8),\
               flags=cv.CV_CALIB_FIX_INTRINSIC)

我使用视差约束(如OpenCV书中所述)来检查结果,得到了约0.0039的平均误差。

原则上,我应该能够将基础矩阵和本质矩阵与我的相机矩阵相关联。所以我做的是:

Mr = asarray(intrinsic_right,dtype=float64)
Ml = asarray(intrinsic_left,dtype=float64)
E = asarray(E)
F = asarray(F)
F2 = dot(dot(inv(Mr).T,E),inv(Ml))

然而,得到的矩阵F2与F完全不相似。我是否做错了什么明显的事情?非常感谢您的帮助。
编辑:dot和inv是来自numpy的。
2个回答

5

StereoCalibrate()返回的E和F矩阵是正确的。F的定义是按比例缩放的,因此如果您要比较返回的F和从E计算出的F矩阵,则需要对它们进行归一化,以确保两者处于相同的比例尺度上。所以当您查看它们时,它们看起来是相同的。StereoCalibrate()会对返回的F进行归一化,因此您需要像在其中一个评论中提到的那样对计算出的F2进行归一化。希望这样更清楚为什么需要这样做。


0

我向你推荐基本矩阵之歌...

但说真的,也许是点积中的某些“标准化”问题吗?标准的numpy dot函数似乎能够正确地将矩阵分解为单个行向量和列向量进行乘法。

例如,如果我执行以下操作:

A = mat(random.rand(3,3))
B = mat(random.rand(3,3))
dot(A,B) == A*B

相反,我想知道是否有助于执行直接的矩阵乘法:

F2 = np.linalg.inv(Mr.T) * E * np.linalg.inv(Ml)

(注:我在这里使用numpy矩阵)


我正在使用numpy的点函数,因为我在处理numpy数组。实际上,我刚刚发现通过F2 /= F2 [2,2]缩放F2可以得到正确的结果。然而,这仍然让我感到困惑,因为根据API,我上面的计算应该是正确的。老实说,我不知道这首歌如何与此相关。我知道什么是基础矩阵,我只想知道为什么OpenCV会出错。 - fabee
啊,好的。矩阵没有归一化会有影响吗?我的意思是,当我进一步使用它时,会得到错误的结果吗?关于那首歌,我很抱歉有点激动。我相信你是开玩笑的。我只是很烦恼函数实际上计算的东西与API中声明的不同。 - fabee
没关系。当事情与API不同的时候,这是很烦人的。我会在有空的时候自己看一下。顺便说一句 - 我之前犯了一个愚蠢的错误,没有将上面的示例转换为 mat() 矩阵。如果这样做,它们就相等了。我已经在上面进行了编辑。 - timlukins
一个快速的最终想法...我记得本质矩阵是用于归一化图像坐标,而基础矩阵是度量的(由校准矩阵应用)。我想知道你的原始校准点是否已经归一化了? - timlukins
也许我的回答更清楚地解释了为什么需要对F2进行规范化。 - fireant
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接