我有一个大矩阵(大约1GB),其中每一行代表我在一个表面采样的点的(x,y)坐标及其z高度。
如何使所有的点远离(x,y)坐标的某个欧几里德距离?
目前我正在做这件事:
% mtx_pointList is a large matrix with each row containing a sample: [x y z].
% We want to get all the samples whose (x,y) point is less than dDistance
% away from the vector: v_center = [x y].
mtx_regionSamples = zeros(0,3);
for k=1:length(mtx_pointList(:,1))
if( norm( mtx_pointList(k,[1 2])-v_center ) < dDistance^2 )
mtx_regionSamples = [ mtx_regionSamples mtx_pointList(k,:) ]
end
end
...但在我的应用程序中,这个循环必须运行大约250k次。
如何让它更快地做同样的事情?
答案 0 :(得分:3)
使用pdist2
(默认选项为欧几里德距离):
ind = pdist2(mtx_pointList(:,[1 2]), v_center) < dDistance; %// logical index
result = mtx_pointList(ind,:);
如果矩阵太大,请将其划分为内存允许的行数,然后循环遍历块。
答案 1 :(得分:3)
如果您没有pdist2
(统计工具箱),这是使用bsxfun
计算距离的一种方法:
da = bsxfun(@minus,mtx_pointList(:,[1 2]),permute(v_center,[3 2 1]));
distances = sqrt(sum(da.^2,2));
然后找到符合您标准的点:
distThresh = 0.5; % for example
indsClose = distances < distThresh
result = mtx_pointList(indsClose,:);
您还可以使用欧几里德(2范数)距离的替代形式
||A-B|| = sqrt ( ||A||^2 + ||B||^2 - 2*A.B )
在MATLAB代码中:
a = mtx_pointList(:,[1 2]); b = v_center;
aa = dot(a,a,2); bb = dot(b,b,2); ab=a*b.'; %' or sum(a.*a,2)
distances = sqrt(aa + bb - 2*ab); % bsxfun needed if b is more than one point
正如路易斯·门多指出的那样,如果您针对sqrt
设置门槛,则无需distThresh^2
。