Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用MATLAB计算摄像机矩阵_Matlab_Matrix_Camera_Computer Vision_Projection - Fatal编程技术网

用MATLAB计算摄像机矩阵

用MATLAB计算摄像机矩阵,matlab,matrix,camera,computer-vision,projection,Matlab,Matrix,Camera,Computer Vision,Projection,我目前正试图计算给定一组世界点(X)及其对应的图像点(X)的相机矩阵p。但是,在测试结果时,P(3 x 4摄影机矩阵)乘以世界点并不能给出正确的对应图像点。但是,只有PX=x的第一列。另一列不会返回近似的图像点 代码: 第一列的输出效果良好: >> p*XX{1} ans = 0.0461 0.0922 0.0154 >> ans/0.0154 ans = 2.9921 5.9841 0.9974 >>

我目前正试图计算给定一组世界点(X)及其对应的图像点(X)的相机矩阵p。但是,在测试结果时,P(3 x 4摄影机矩阵)乘以世界点并不能给出正确的对应图像点。但是,只有PX=x的第一列。另一列不会返回近似的图像点

代码:

第一列的输出效果良好:

>> p*XX{1}

ans =

    0.0461
    0.0922
    0.0154

>> ans/0.0154

ans =

    2.9921
    5.9841
    0.9974

>> xx{1}

ans =

     3
     6
     1
第二列的输出无效:

>> p*XX{2}

ans =

    0.5202
    0.0867
    0.1734

>> ans/0.1734

ans =

    2.9999
    0.5000
    1.0000

>> xx{2}

ans =

     6
     1
     2

顺便说一下,有人告诉我,在计算相机矩阵之前,我需要规范化世界点和图像点。我还没有完成这一步,也不知道怎么做。如果这是导致问题的原因,请说明可以采取的措施。先谢谢你

这是因为您没有正确地索引到矩阵中。您正在使用线性索引来访问矩阵的每一列。在这种情况下,您的
for
循环需要独立地访问每一列。因此,
for
循环的每次迭代必须访问3D点的4个元素组和2D点的3个元素组

因此,您只需对
for
循环执行以下操作:

for i = 0:(nX-1)
    XX{i+1} = transpose(X(4*i + 1 : 4*(i + 1)));
end

for i = 0:(nx-1)
    xx{i+1} = transpose(x(3*i + 1 : 3*(i + 1)));
end
A = [zeros(N, 4) -X.' bsxfun(@times, x(2,:).', X.'); 
     X.' zeros(N, 4) bsxfun(@times, -x(1,:).', X.')];
在此之后,代码应该可以正常工作。为了验证,我们可以循环通过每个3D点,并在使用单元时确定其2D等效值:

out = zeros(size(xx)); % Declare output matrix
for ii = 1 : numel(XX) % For each 3D point...
    out(:,ii) = p * XX{ii}; % Transform the point
    out(:,ii) = out(:,ii) / out(end,ii); % Normalize
end
因此,我们得到:

>> out

out =

    3.0000    2.0000    1.0000
    6.0000    5.0000    4.0000
    1.0000    1.0000    1.0000
与您的
x
进行比较:

>> x

x =

     3     2     1
     6     5     4
     1     1     1
建议-使用矢量化 如果我能提出一些建议,请不要在这里使用单元格数组。可以创建方程矩阵,以便使用矢量化进行求解。具体而言,您可以直接创建矩阵
A
,而无需为循环创建任何

for i = 0:(nX-1)
    XX{i+1} = transpose(X(4*i + 1 : 4*(i + 1)));
end

for i = 0:(nx-1)
    xx{i+1} = transpose(x(3*i + 1 : 3*(i + 1)));
end
A = [zeros(N, 4) -X.' bsxfun(@times, x(2,:).', X.'); 
     X.' zeros(N, 4) bsxfun(@times, -x(1,:).', X.')];
如果您拥有MATLAB R2016b及更高版本,您可以通过内部广播实现这一点:

A = [zeros(N, 4) -X.' x(2,:).' .* X.'; 
     X.' zeros(N, 4) -x(1,:).' .* X.']
请注意,由于矢量化,与原始矩阵
A
相比,您将看到行被洗牌。因为我们正在求解矩阵
A
的空空间,所以洗牌行没有效果。因此,您的代码可以简化为:

X = [1 2 3; 4 5 6; 7 8 9; 1 1 1];
x = [3 2 1; 6 5 4; 1 1 1];

A = [zeros(N, 4) -X.' bsxfun(@times, x(2,:).', X.'); 
     X.' zeros(N, 4) bsxfun(@times, -x(1,:).', X.')];

% Use this for MATLAB R2016b and up
% A = [zeros(N, 4) -X.' x(2,:).' .* X.'; 
%      X.' zeros(N, 4) -x(1,:).' .* X.']

[u, s, v] = svd(A);
p = v(:, end);
p = reshape(p, 4, 3).';
要最终计算输出矩阵,只需使用简单的矩阵乘法。使用单元格这一事实要求您必须使用
for
循环,而使用矩阵乘法则要快得多:

out = p * X;
然后,您可以获取结果的最后一行,并将其他每一行除以此行

out = bsxfun(@rdivide, out, out(end,:));
同样,使用MATLAB R2016b及更高版本,您可以这样做:

out = out ./ out(end,:);

求求你!可能是
x(i+1:3+i)
中的索引错误。在命令窗口中单独运行此部件。这就是你想要的吗?我回答你的问题了吗?@rayryeng是的,现在它工作得很好!谢谢你详尽的回答。非常感谢@夏文森一点问题都没有。如果你愿意,我可以谈谈为什么你需要规范化点。不过,我觉得这应该是另一个问题。在此特定实例中,2D和3D点之间的值的大小大致相同,因此不需要标准化。