如何从大矩阵中获得符合某些条件的所有行?

时间:2014-01-23 19:24:09

标签: performance matlab if-statement for-loop matrix

我有一个大矩阵(大约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次。

如何让它更快地做同样的事情?

2 个答案:

答案 0 :(得分:3)

使用pdist2(默认选项为欧几里德距离):

ind = pdist2(mtx_pointList(:,[1 2]), v_center) < dDistance; %// logical index
result = mtx_pointList(ind,:);

如果矩阵太大,请将其划分为内存允许的行数,然后循环遍历块。

答案 1 :(得分:3)

bsxfun

如果您没有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