【问题标题】:Calculate pairwise distances of xyz values within a matrix using matlab使用matlab计算矩阵内xyz值的成对距离
【发布时间】:2020-04-12 10:38:40
【问题描述】:

我是 Matlab 的新手,并且已经尝试解决这个问题好几个星期了。

我有几个大型矩阵,它们的行数各不相同,尽管它们都有 69 列。在这些矩阵中有 23 个 xyz 值,例如第 1,2,3 列是第 1 点的 x,y,z 值,第 4,5,6 列是第 2 点的 x,y,z 值,依此类推,直到第 69 列。

每个矩阵有 1000 多行,每一行代表一个时间点。 我正在尝试使用 for 循环来计算第 1 行和第 2 行之间的差异,然后是第 2 行和第 3 行,然后是第 3 和第 4 行等,使用毕达哥拉斯定理。 本质上,最终输出应该是距离值的 N*23 矩阵,但我在生成 for 循环时遇到了困难。

与此同时,我一直在尝试使用较小的 4*3 数组来解决这个问题,(n 是矩阵)没有运气。

for i = 1:row 

   for j = 1:col
        pythag(i,j) = sqrt((n(i,1)-n(j,1))^2 +((n(i,2)-n(j,2))^2 +((n(i,3)-n(j,3))^2)));
    end
end

任何帮助将不胜感激。

【问题讨论】:

  • 您的句子“我有大量的 N*69 矩阵”与帖子的其余部分没有解决。我假设您有一个包含 N 行的大型矩阵。我希望我是对的,因为我的回答是基于这个假设。请编辑您的问题并使其更清楚。

标签: matlab 3d distance


【解决方案1】:

您实际上可以在一行代码中解决问题。

  • 最终输出应该是 (N-1)*23 而不是 N*23 矩阵。
  • 在您的循环中,n 中的列索引应该在 j 的每一个提升中提升 3
  • 您还需要从行i 中减去行i+1

我将您的矩阵 n 重命名为 A

这是一个使用 for 循环的示例解决方案(请阅读 cmets):

%I have a large number of N*69 matrices
%Within these matrices are 23 xyz values, e.g. column 1,2,3 are the x,y,z values for point 1, column 4,5,6 the x,y,z values for point 2 and so on, up to column 69.
%One row:
%A = [x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4]; %For example take 4 xyz values (instead of 23)

%There are over 1000 rows for each matrix,
%Example include 4 rows:
% A = [x11, y11, z11, x12, y12, z12, x13, y13, z13, x14, y14, z14;...
%      x21, y21, z21, x22, y22, z22, x23, y23, z23, x24, y24, z24;...
%      x31, y31, z31, x32, y32, z32, x33, y33, z33, x34, y34, z34;...
%      x41, y41, z41, x42, y42, z42, x43, y43, z43, x44, y44, z44];

%Initialize A with arbitrary values (I decided to name the matrix A instead of n).
A = [magic(4) magic(4) magic(4)];

% A =  [16     2     3    13    16     2     3    13    16     2     3    13
%        5    11    10     8     5    11    10     8     5    11    10     8
%        9     7     6    12     9     7     6    12     9     7     6    12
%        4    14    15     1     4    14    15     1     4    14    15     1];


%Calculate the difference between row 1 and 2, then row 2 and 3, then 3 and 4
%Essentially, the end output should be a N*23 matrix. Wrong!!! it should be (N-1)*23 matrix

%Assume N is the number of rows (over 1000 rows).
N = size(A, 1);

%Size of pythag matrix is (N-1)x(69/3) and in the example size is 3x4
row = N-1;
col = size(A,2)/3;

%Initialize output matrix with zeros.
pythag = zeros(row, col);

%Solving using a nested for loops:  
for i = 1:row     
    %k, k+1, k+2 are the x,y,z, columns indeces in matrix A
    k = 1;

    for j = 1:col
        %pythag(i,j) = sqrt((n(i,1)-n(j,1))^2 +((n(i,2)-n(j,2))^2 +((n(i,3)-n(j,3))^2)));

        %We want the to distance from row i+1 to row i (in matrix A).
        pythag(i, j) = sqrt((A(i+1, k)-A(i, k))^2 +((A(i+1, k+1)-A(i, k+1))^2 +((A(i+1, k+2)-A(i, k+2))^2)));
        %                         |                           |                            |
        %                         x                           y                            z

        %The column index in A must skip by 3 for each increment of j
        k = k + 3;
    end
end

更优雅:将sqrt(x^2 + y^2 + z^2) 替换为norm([x,y,z]):

for i = 1:row
    %k, k+1, k+2 are the x,y,z, columns indices in matrix A
    k = 1;

    for j = 1:col
        %We want the to distance from row i+1 to row i (in matrix A).
        pythag(i, j) = norm([A(i+1, k) - A(i, k), A(i+1, k+1) - A(i, k+1), A(i+1, k+2) - A(i, k+2)]);

        %The column index in A must skip by 3 for each increment of j
        k = k + 3;
    end
end

矢量化内循环(使用vecnorm 而不是norm):

for i = 1:row       
    pythag(i, 1:col) = vecnorm([A(i+1, 1:3:end) - A(i, 1:3:end); A(i+1, 2:3:end) - A(i, 2:3:end); A(i+1, 3:3:end) - A(i, 3:3:end)]);
end

矢量化外循环(与vecnorm 混淆 - 回到毕达哥拉斯):

pythag = sqrt((A(2:end, 1:3:end)-A(1:end-1, 1:3:end)).^2 +((A(2:end, 2:3:end)-A(1:end-1, 2:3:end)).^2 +((A(2:end, 3:3:end)-A(1:end-1, 3:3:end)).^2)));

【讨论】:

    【解决方案2】:

    充分利用 Matlab 的矢量计算功能:您可以省略内部循环并立即计算矢量信息的距离(注意您需要提供sum() 的方向)。 Matlab 将所有数据存储在 RAM 一致性中,即它有时必须随着向量的增长将向量复制到 RAM 中的不同位置。因此,请在开始时分配完整空间,例如NaN()

    % allocate memory
    pythag = NaN(row,col);
    for i = 1:row 
        pythag(i,:) = sqrt(sum( (n(i,1:3)-n(:,1:3)).^2,2 ));
    end
    

    如果您提供一个最小的工作示例,我们可以检查您的完整代码并引导您解决问题。

    【讨论】:

    • 您的解决方案不是“第 1 行和第 2 行、第 2 行和第 3 行、第 3 行和第 4 行等之间的差异”
    • @Rotem,哦,我明白了。比diffcommand 可以进一步减少计算。我可以用 MVE 更好地展示它
    猜你喜欢
    • 1970-01-01
    • 2018-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-08
    • 2015-09-14
    • 1970-01-01
    相关资源
    最近更新 更多