在Matlab中快速去除冗余点的方法



我在Matlab中合并了两个pointCloud对象,比如pc1和pc2。pc1是参考云,即,在组合云之前,需要移除来自pc2的与来自pc1的点相等或非常接近的所有点。

澄清:

  • 我知道函数pcmerge,它几乎在做我想要的事情,但我肯定需要删除多余的点,并且平均这些点不是的选项

  • 每个点云的大小大约是500000,我必须比较其中的许多(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
    
  • 我有一个处理alpha形状的更快的解决方案(仍然很慢,但比解决方案1更快(:我在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
    

我很期待你的想法!如果需要,请毫不犹豫地询问更多信息——我是这个平台的新手。非常感谢。

您可以使用ismembertolByRows选项来检测冗余点。但考虑一下,它使用的不是球面邻域,而是三次邻域。假设您有两个矩阵pc1pc2,每个矩阵有3列和一个容差tol:

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

相关内容

  • 没有找到相关文章

最新更新