【问题标题】:Analysis of a 3D point cloud by projection in a 2D surface通过在 2D 表面中的投影分析 3D 点云
【发布时间】:2013-11-20 19:44:02
【问题描述】:

我有一个 3D 点云 (XYZ),其中 Z 可以是位置或能量。我想以 n-by-m 网格(在我的问题n = m)中将它们投影到 2D 表面上,每个网格单元的值为Z 的最大差值,如果Z 是位置,或求和值超过Z,如果Z 是能量。

例如,在0 <= (x,y) <= 20 的范围内,有 500 个点。假设 xy 平面有 n-by-m 个分区,例如4-by-4;我的意思是在xy 两个方向上,我们有4 个分区,间隔为5(使其最大为20。现在,每个单元格都应该有一个总和值,或者Z 值的最大差异,这些点在定义的 xy 平面中的相应列中。

我做了一个简单的 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

如何在没有循环的情况下做到这一点?

【问题讨论】:

    标签: matlab matrix vectorization projection


    【解决方案1】:

    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 数量)

    【讨论】:

    • +1 两个答案。很高兴看到accumarray 被巧妙地使用。 accumarray 有一个明显的学习曲线,但一旦你掌握它,它就会打开大门。
    • @chappjc 我喜欢所有那些我最初发现几乎没用的输入参数(到 accumarray),结果却完全符合我的需要 ;-)
    【解决方案2】:

    备注:

    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); 
    

    【讨论】:

      猜你喜欢
      • 2011-07-29
      • 1970-01-01
      • 1970-01-01
      • 2019-02-01
      • 1970-01-01
      • 2023-03-08
      • 2019-04-10
      • 2010-09-12
      • 2012-09-03
      相关资源
      最近更新 更多