方法#1
For a N x 2
大小的点/像素数组,你可以避免permute
正如建议的路易斯的其他解决方案,这可能会减慢速度,有一种"permute-unrolled"
它的版本,也让我们bsxfun
努力实现2D
数组而不是3D
数组,性能一定更好。
因此,假设簇被排序为N x 2
大小的数组,你可以尝试其他bsxfun
基于方法-
%// Get a's and b's
im_a = im(:,:,2);
im_b = im(:,:,3);
%// Get the minimum indices that correspond to the cluster IDs
[~,idx] = min(bsxfun(@minus,im_a(:),clusters(:,1).').^2 + ...
bsxfun(@minus,im_b(:),clusters(:,2).').^2,[],2);
idx = reshape(idx,size(im,1),[]);
方法#2
您可以尝试另一种利用的方法fast matrix multiplication in MATLAB并基于这个智能解决方案 -
d = 2; %// dimension of the problem size
im23 = reshape(im(:,:,2:3),[],2);
numA = size(im23,1);
numB = size(clusters,1);
A_ext = zeros(numA,3*d);
B_ext = zeros(numB,3*d);
for id = 1:d
A_ext(:,3*id-2:3*id) = [ones(numA,1), -2*im23(:,id), im23(:,id).^2 ];
B_ext(:,3*id-2:3*id) = [clusters(:,id).^2 , clusters(:,id), ones(numB,1)];
end
[~, idx] = min(A_ext * B_ext',[],2); %//'
idx = reshape(idx, size(im,1),[]); %// Desired IDs
基于矩阵乘法的距离矩阵计算是怎么回事?
让我们考虑两个矩阵A
and B
我们要计算他们之间的距离矩阵。为了接下来更容易解释,让我们考虑一下A
as 3 x 2
and B
as 4 x 2
大小的数组,从而表明我们正在处理 X-Y 点。如果我们有A
as N x 3
and B
as M x 3
大小的数组,那么那些将是X-Y-Z
points.
现在,如果我们必须手动计算距离矩阵平方的第一个元素,它看起来像这样 –
first_element = ( A(1,1) – B(1,1) )^2 + ( A(1,2) – B(1,2) )^2
这将是——
first_element = A(1,1)^2 + B(1,1)^2 -2*A(1,1)* B(1,1) + ...
A(1,2)^2 + B(1,2)^2 -2*A(1,2)* B(1,2) … Equation (1)
现在,根据我们提出的矩阵乘法,如果您检查A_ext
and B_ext
早期代码中的循环结束后,它们将如下所示 –
![enter image description here](https://i.stack.imgur.com/U3M4w.png)
![enter image description here](https://i.stack.imgur.com/aMR1R.png)
因此,如果您执行之间的矩阵乘法A_ext
并转置B_ext
,乘积的第一个元素将是第一行之间的元素乘法之和A_ext
and B_ext
,即这些的总和 –
![enter image description here](https://i.stack.imgur.com/I08OI.png)
结果将与获得的结果相同Equation (1)
早些时候。这将继续适用于所有元素A
反对所有要素B
与在同一列中A
。因此,我们最终会得到完整的平方距离矩阵。这就是全部了!
矢量化变体
基于距离矩阵计算的矩阵乘法的矢量化变体是可能的,尽管它们没有看到任何重大的性能改进。接下来列出了两个这样的变体。
变化#1
[nA,dim] = size(A);
nB = size(B,1);
A_ext = ones(nA,dim*3);
A_ext(:,2:3:end) = -2*A;
A_ext(:,3:3:end) = A.^2;
B_ext = ones(nB,dim*3);
B_ext(:,1:3:end) = B.^2;
B_ext(:,2:3:end) = B;
distmat = A_ext * B_ext.';
变化#2
[nA,dim] = size(A);
nB = size(B,1);
A_ext = [ones(nA*dim,1) -2*A(:) A(:).^2];
B_ext = [B(:).^2 B(:) ones(nB*dim,1)];
A_ext = reshape(permute(reshape(A_ext,nA,dim,[]),[1 3 2]),nA,[]);
B_ext = reshape(permute(reshape(B_ext,nB,dim,[]),[1 3 2]),nB,[]);
distmat = A_ext * B_ext.';
因此,这些也可以被视为实验版本。