Java 基本矩阵的分解:R和T的四种可能解的验证
我想用OpenCV从运动中构造一些结构。 到目前为止,我有基本矩阵和基本矩阵。 有了essentialmatrix,我正在做SVD,以获得R和T 我的问题是,对于R和T,我有两个可能的解,这导致了整个姿势的4个解,其中只有一个解是正确的。 如何找到正确的解决方案 这是我的密码:Java 基本矩阵的分解:R和T的四种可能解的验证,java,opencv,computer-vision,Java,Opencv,Computer Vision,我想用OpenCV从运动中构造一些结构。 到目前为止,我有基本矩阵和基本矩阵。 有了essentialmatrix,我正在做SVD,以获得R和T 我的问题是,对于R和T,我有两个可能的解,这导致了整个姿势的4个解,其中只有一个解是正确的。 如何找到正确的解决方案 这是我的密码: private void calculateRT(Mat E, Mat R, Mat T){ Mat w = new Mat(); Mat u = new Mat(); Mat vt = new
private void calculateRT(Mat E, Mat R, Mat T){
Mat w = new Mat();
Mat u = new Mat();
Mat vt = new Mat();
Mat diag = new Mat(3,3,CvType.CV_64FC1);
double[] diagVal = {1,0,0,0,1,0,0,0,1};
diag.put(0, 0, diagVal);
Mat newE = new Mat(3,3,CvType.CV_64FC1);
Core.SVDecomp(E, w, u, vt, Core.DECOMP_SVD);
Core.gemm(u, diag, 1, vt, 1, newE);
Core.SVDecomp(newE, w, u, vt, Core.DECOMP_SVD);
publishProgress("U: " + u.dump());
publishProgress("W: " + w.dump());
publishProgress("vt:" + vt.dump());
double[] W_Values = {0,-1,0,1,0,0,0,0,1};
Mat W = new Mat(new Size(3,3), CvType.CV_64FC1);
W.put(0, 0, W_Values);
double[] Wt_values = {0,1,0-1,0,0,0,0,1};
Mat Wt = new Mat(new Size(3,3), CvType.CV_64FC1);
Wt.put(0,0,Wt_values);
Mat R1 = new Mat();
Mat R2 = new Mat();
// u * W * vt = R
Core.gemm(u, Wt, 1, vt, 1, R2);
Core.gemm(u, W, 1, vt, 1, R1);
publishProgress("R: " + R.dump());
// +- T (2 possible solutions for T)
Mat T1 = new Mat();
Mat T2 = new Mat();
// T = u.t
u.col(2).copyTo(T1);
publishProgress("T : " + T.dump());
Core.multiply(T, new Scalar(-1.0, -1.0, -1.0), T2);
// TODO Here I have to find the correct combination for R1 R2 and T1 T2
}
从基本矩阵重建两个相机的相对欧几里得姿态时,理论上存在歧义。这种模糊性与以下事实有关:给定图像中的二维点,经典针孔相机模型无法判断相应的三维点是在相机前面还是在相机后面。为了消除这种模糊性,您需要知道图像中的一个点对应关系:因为这两个2D点被假定为位于两个摄像头前面的单个3D点的投影(因为它在两个图像中都可见),这将允许选择正确的R和T 为此,C.Ressl()在以下博士论文的§6.1.4(第47页)“三焦点张量的几何、约束和计算”中解释了一种方法。下面给出了该方法的概要。我将用x1和x2表示两个对应的2D点,用K1和K2表示两个摄像机矩阵,用E12表示基本矩阵 一,。计算基本矩阵的奇异值分解
E12=U*S*V'
。如果det(U)<0
设置U=-U
。如果det(V)<0
设置V=-V
二,。定义W=[0,-1,0;1,0,0;0,0,1]
,R2=U*W*V'
和T2=U的第三列
iii.定义M=[R2'*T2]x
,X1=M*inv(K1)*X1
和X2=M*R2'*inv(K2)*X2
iv.如果X1(3)*X2(3)<0
,则设置R2=U*W'*V'
,并重新计算M
和X1
五,。如果X1(3)<0
setT2=-T2
vi.定义P1|E=K1*[I|0]
和P2|E=K2*[R2|T2]
符号”
表示转置,步骤iii中使用的符号[.]x
对应于斜对称运算符。在3x1向量e=[e_1;e_2;e_3]
上应用斜对称运算符会产生以下结果(请参见):
最后,请注意,
T2
的范数始终为1,因为它是正交矩阵的列之一。这意味着您将无法恢复两个摄影机之间的真实距离。为此,您需要知道场景中两点之间的真实距离,并将其考虑在内,以计算摄像机之间的真实距离。我不太理解iii。我有两个点x1和x2(在图像坐标中,表示x1=(x,y)作为像素坐标)和摄像机内部坐标,但我不明白怎么计算M,X1,X2@glethien对于M,首先计算转置时间R2
T2,然后对结果应用斜对称运算符[.]x
(有关定义,请参阅Wikipedia链接)。因此M
是一个3x3矩阵。对于X1
和X2
,我在矩阵乘法中使用了两种不同的符号,但它们是相同的(我编辑了我的帖子来纠正这一点)。此外,x1
和x2
应在齐次坐标中,即3x1向量,如x1=[x;y;1]
@glethien。此外,请注意,如果在步骤iv中修改了R2,则在执行步骤v之前需要相应地更新M和x1。我在帖子里说得更清楚了。
[e]x = [0,-e_3,e_2; e_3,0,-e_1; -e_2,e_1,0]