matlab - Matlab去除多余点的快速方法

标签 matlab performance point-clouds

我在 Matlab 中合并了两个点云对象,比方说 pc1 和 pc2。 pc1 是引用云,即 pc2 中与 pc1 中的点相等或非常接近的所有点都需要在组合云之前移除。

说明:

  • 我知道 pcmerge 函数,它几乎可以满足我的要求 - 但我绝对需要删除多余的点并且不能对这些点进行平均

  • 每个点云大小约为 500,000,我必须比较其中的许多点云 (100)。这就是速度很重要的原因。

  • 我希望能够在 pc1 的每个点周围定义一个半径,以给出“冗余”的标准。但是为了提高速度,可以进行一些简化(参见我的第二种解决方法)。

解决方法:

  • 一个有效但非常慢的解决方案是寻找 pc2 中的每个点的最近邻居:

    function [ pc ] = pcaddcloud( pc1, pc2, res )
    
    limits = overlapRange(pc2, pc1);
    pc1idx = findPointsInROI(pc2, limits);
    pc2Overlap = select(pc2, pc1idx);
    idx = findPointsInROI(pc1, limits);
    pc1Overlap = select(pc1, idx);
    endi = pc2Overlap.Count;
    pc2Overlap = pc2Overlap.Location;
    for i=1:endi
        [idx, ~] = findNeighborsInRadius(pc1Overlap, pc2Overlap(i,:), res);
        % keep only indices of redundant points to delete them later
        if isempty(idx)
            pc1idx(i) = 0;
        end
    end
    pc1idx(pc1idx==0) = [];
    pc2 = pc2.Location;
    pc2(pc1idx,:) = [];
    pc = pointCloud([pc1.Location; pc2]);
    end
    
    % Compute the bounding box of overlapped region (from pcmerge)
    function rangeLimits = overlapRange(pcA, pcB)
    xlimA = pcA.XLimits;
    ylimA = pcA.YLimits;
    zlimA = pcA.ZLimits;
    
    xlimB = pcB.XLimits;
    ylimB = pcB.YLimits;
    zlimB = pcB.ZLimits;
    
    if (xlimA(1) > xlimB(2) || xlimA(2) < xlimB(1) || ...
            ylimA(1) > ylimB(2) || ylimA(2) < ylimB(1) || ...
            zlimA(1) > zlimB(2) || zlimA(2) < zlimB(1))
        % No overlap
        rangeLimits = [];
    else
        rangeLimits = [ min(xlimA(1),xlimB(1)), max(xlimA(2),xlimB(2)); ...
            min(ylimA(1),ylimB(1)), max(ylimA(2),ylimB(2)); ...
            min(zlimA(1),zlimB(1)), max(zlimA(2),zlimB(2))];
    end
    end
    
  • 我有一个更快的解决方案(仍然很慢,但比解决方案 1 更快)使用 alpha 形状:我在 pc1 周围定义一个外壳并决定 pc2 的点是否在内部。缺点:仅“略微超出”(即靠近 pc1 的点但不在 alpha 形状内)的点不会被检测为冗余。

    function [ pc ] = pcaddcloud( pc1, pc2 )
    
    limits = overlapRange(pc2, pc1);
    pc2 = pc2.Location;
    pc1 = pc1.Location;
    %seems to be faster than findPointsInROI:
    pc2Overlap = pc2(pc2(:,1)>=limits(1,1)&pc2(:,1)<=limits(1,2) ...
        &pc2(:,2)>=limits(2,1)&pc2(:,2)<=limits(2,2)...
        &pc2(:,3)>=limits(3,1)&pc2(:,3)<=limits(3,2),:);
    pc2idx = find(pc2(:,1)>=limits(1,1)&pc2(:,1)<=limits(1,2) ...
        &pc2(:,2)>=limits(2,1)&pc2(:,2)<=limits(2,2)...
        &pc2(:,3)>=limits(3,1)&pc2(:,3)<=limits(3,2));
    pc1Overlap = pc1(pc1(:,1)>=limits(1,1)&pc1(:,1)<=limits(1,2) ...
        &pc1(:,2)>=limits(2,1)&pc1(:,2)<=limits(2,2)...
        &pc1(:,3)>=limits(3,1)&pc1(:,3)<=limits(3,2),:);
    
    shape = alphaShape(double(pc1Overlap));
    in = inShape(shape, double(pc2Overlap));
    pc2idx(~in) = [];
    pc2(pc2idx,:) = [];
    pc = pointCloud([pc1; pc2]);
    
    end
    
    % Compute the bounding box of overlapped region (from pcmerge)
    function rangeLimits = overlapRange(pcA, pcB)
    xlimA = pcA.XLimits;
    ylimA = pcA.YLimits;
    zlimA = pcA.ZLimits;
    
    xlimB = pcB.XLimits;
    ylimB = pcB.YLimits;
    zlimB = pcB.ZLimits;
    
    if (xlimA(1) > xlimB(2) || xlimA(2) < xlimB(1) || ...
            ylimA(1) > ylimB(2) || ylimA(2) < ylimB(1) || ...
            zlimA(1) > zlimB(2) || zlimA(2) < zlimB(1))
        % No overlap
        rangeLimits = [];
    else
        rangeLimits = [ min(xlimA(1),xlimB(1)), max(xlimA(2),xlimB(2)); ...
            min(ylimA(1),ylimB(1)), max(ylimA(2),ylimB(2)); ...
            min(zlimA(1),zlimB(1)), max(zlimA(2),zlimB(2))];
    end
    end
    

我期待着您的想法!如果需要,请随时询问更多信息 - 我是这个平台的新手。谢谢!

最佳答案

您可以使用 ismembertol使用 ByRows 选项来检测冗余点。但是请考虑它使用立方体邻域而不是球形邻域。 假设您有两个矩阵 pc1pc2,每个矩阵都有 3 列和一个公差 tol:

idx = ismembertol(pc2, pc1, tol,'ByRows', true, 'DataScale' , 1);
result = [pc1; pc2(~idx,:)];

关于matlab - Matlab去除多余点的快速方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53008033/

相关文章:

matlab - 如何将每行都带有复选框的表/结构导入到 GUI,然后将选择列表导出到 MATLAB?

MATLAB 同步代码

c++ - 在多线程环境中使用 auto_ptr 交换对象而不锁定是安全的吗?

javascript - 如果我在 for 循环中调用一个包含 for 循环的函数,那是 O(n^2) 时间还是 O(n)?

python - Open3D 向 ICP 注册显示错误为 0 并返回输入转换

user-interface - 如何防止 MATLAB GUI 中的 LATEX 标签变得模糊?

performance - 为什么 IsNull 比合并(相同查询)慢两倍?

c++ - 改变点的颜色openGL3.3

python - 从深度图计算视野

python - 通过 Python 但通过 Linux 命令终端调用 MATLAB