通过在2D平面上投影分析3D点云

7
我有一个三维点云(XYZ),其中Z可以是位置或能量。我希望将它们投影到一个n-by-m网格的2D表面上(在我的问题中,n=m),以便每个网格单元格具有Z的最大差值的值,如果Z是位置,则具有求和值的值,如果Z为能量。
例如,在范围0 <= (x,y) <= 20内,有500个点。假设xy平面具有n-by-m分区,例如4-by-4;我指的是在xy两个方向上,我们有4个间隔为5的分区(使其最大为20)。现在,这些单元格中的每一个都应该具有相应列中那些处于定义的xy平面中的点的Z值的求和或最大差值的值。
我为测试创建了一个简单的XYZ数组,如下所示,在这种情况下,Z表示每个点的能量。
n=1;
for i=1:2*round(random('Uniform',1,5))
    for j=1:2*round(random('Uniform',1,5))
        table(n,:)=[i,j,random('normal',1,1)];
        n=n+1;
    end
end

如何在不使用循环的情况下完成此操作?
2个回答

5

accumarray函数非常适合这种任务。首先,我定义示例数据:

table = [ 20*rand(1000,1) 30*rand(1000,1) 40*rand(1000,1)]; % random data
x_partition = 0:2:20; % partition of x axis
y_partition = 0:5:30; % partition of y axis

我假设:
  • table 的三列分别表示 x、y 和 z。
  • 没有一个点的 x 坐标小于你网格的第一条边或大于最后一条边,y 坐标同理。也就是说,该网格覆盖了所有的点。
  • 如果一个 bin 不包含值,结果应该是 NaN(如果你想要其他填充值,请更改 accumarray 的最后一个参数)。
然后:
L = size(table,1);
M = length(x_partition);
N = length(y_partition);
[~, ii] = max(repmat(table(:,1),1,M) <= repmat(x_partition,L,1),[],2);
[~, jj] = max(repmat(table(:,2),1,N) <= repmat(y_partition,L,1),[],2);
ii = ii-1; % by assumption, all values in ii will be at least 2, so we subtract 1
jj = jj-1; % same for jj
result_maxdif = accumarray([ii jj], table(:,3), [M-1 N-1], @(v) max(v)-min(v), NaN);
result_sum = accumarray([ii jj], table(:,3), [M-1 N-1], @sum, NaN);

代码说明:

  • 关键在于获取iijj,它们给出每个点所在的x和y方向bin的索引。我使用了repmat来完成。虽然使用bsxfun可能更好,但它不支持@max的多输出版本。
  • 结果的大小为 (M-1) x (N-1)(每个维度上bin的数量)。

2
两个答案都加一。很高兴看到accumarray被巧妙地使用。使用accumarray确实有一个明显的学习曲线,但是一旦掌握了它,就会打开新的大门。 - chappjc
@chappjc 我喜欢 accumarray 的所有输入参数,最初我几乎认为它们没有用处,结果发现它们恰好满足我的需求;-) - Luis Mendo

4

备注:

  1. 所有这些都可以通过Python Pandas和切割方法几乎成为一行代码。
  2. 我已经重新编写了您的随机云初始化。

你可以做的是:

  1. 通过meshgrid布置xy网格,
  2. 在xy上投影云(简单的边缘化),
  3. 通过kd-tree搜索找到最近的网格点,即为每个云点分配一个网格节点的标签,
  4. 按标签分组数据并通过accumarray评估您的局部统计量。

下面是一个工作示例:

 samples = 500;
 %data extrema
 xl = 0; xr = 1; yl = 0; yr = 1;

 % # grid points
 sz = 20;
 % # new random cloud    
 table = [random('Uniform',xl,xr,[samples,1]) , random('Uniform',yr,yl,[samples,1]), random('normal',1,1,[samples,1])];

 figure; scatter3(table(:,1),table(:,2),table(:,3));

 % # grid construction
 xx = linspace(xl,xr,sz); yy = linspace(yl,yr,sz);
 [X,Y] = meshgrid(xx,yy);
 grid_centers = [X(:),Y(:)];

 x = table(:,1); y = table(:,2); 

 % # kd-tree
 kdtreeobj = KDTreeSearcher(grid_centers);
 clss = kdtreeobj.knnsearch([x,y]); % # classification

 % # defintion of local statistic
 local_stat = @(x)sum(x) % # for total energy
 % local_stat = @(x)max(x)-min(x) % # for position off-set

 % # data_grouping
 class_stat = accumarray(clss,table(:,3),[],local_stat );       
 class_stat_M  = reshape(class_stat , size(X)); % # 2D reshaping

 figure; contourf(xx,yy,class_stat_M,20); 

enter image description here enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接