矢量化矢量之间的距离计算

时间:2014-06-21 20:45:07

标签: image matlab for-loop vectorization

我有一个3 X 1000(以及后来的3 X 10 000)矩阵cord,它包含我的像素的三维坐标。

我的意图是计算所有像素之间的距离,我用for循环(见下文)来做,但我将很快计算出巨大的矩阵,并且我想知道我是否可以将代码矢量化为让它更快......?

dist = zeros(size(cord,2),size(cord,2)); 
for i = 1:size(cord,2)
    for j = 1:size(cord,2)
        dist(i,j) = norm(cord(:,i)-cord(:,j));
        dist(j,i) = dist(i,j);
    end 
end

3 个答案:

答案 0 :(得分:3)

pdist正是如此。需要squareform才能以方形对称矩阵的形式得到结果:

dist = squareform(pdist(cord.'));

答案 1 :(得分:1)

方法1(使用bsxfun进行矢量化评价) -

squeeze(sqrt(sum(bsxfun(@minus,cord,permute(cord,[1 3 2])).^2)))

不确定这是否会更快。

方法2 -

受此very smart approach的启发以及海报的所有信用。这里发布的代码只是针对您的情况稍作自定义,并希望在运行时方面略微更好。这是 -

A = cord'; %//'
numA = size(cord,2);
helpA = ones(numA,9);
helpB = ones(numA,9);
for idx = 1:3
    sqA_idx = A(:,idx).^2;
    helpA(:,3*idx-1:3*idx) = [-2*A(:,idx), sqA_idx ];
    helpB(:,3*idx-2:3*idx-1) = [sqA_idx , A(:,idx)];
end
dist1 = sqrt(helpA * helpB'); %// desired output

答案 2 :(得分:0)

从您的代码中,您已经认识到dist矩阵是对称的

dist(i,j) = norm(cord(:,i)-cord(:,j));
dist(j,i) = dist(i,j);

您可以更改内部循环以解决此问题,并将所需计算量的大约一半减少

for j = i:size(cord,2)

此外,我们可以在每次迭代时避免dist(j,i) = dist(i,j);,最后通过提取dist的上三角形部分并将其转置添加到dist矩阵来实现对称性

dist = zeros(size(cord,2),size(cord,2)); 
for i = 1:size(cord,2)
    for j = i:size(cord,2)
        dist(i,j) = norm(cord(:,i)-cord(:,j));
    end 
end
dist = dist + triu(dist)';

上面的添加很好,因为主对角线都是零。

它仍然表现不佳,所以我们应该利用矢量化。我们可以对内循环

进行如下操作
dist = zeros(size(cord,2),size(cord,2)); 
for i = 1:size(cord,2)
    dist(i,i+1:end) = sum((repmat(cord(:,i),1,size(cord,2)-i)-cord(:,i+1:end)).^2);
end
dist = dist + triu(dist)';
dist = sqrt(dist);

对于cord中的每个元素,我们需要计算与跟随它的所有其他元素的距离。我们使用repmat重现元素,以便我们可以从后面的每个元素中减去它,而不需要循环。差异被平方并求和并分配给dist矩阵。我们处理对称性,然后取矩阵的平方根来完成norm操作。

使用tictoc,使用随机线(cord = rand(3,num);)计算原始距离大约需要93秒。这个版本花了~2.8。