【问题标题】:How to find the order of discrete point-set efficiently?如何有效地找到离散点集的顺序?
【发布时间】:2016-09-21 02:15:04
【问题描述】:

我有一个平面上的一系列离散点,但是,它们的顺序是分散的。这是一个例子:

为了用平滑的曲线将它们连接起来,我写了一个findSmoothBoundary()来实现平滑的边界。

代码

    function findSmoothBoundary(boundaryPointSet)
        %initialize the current point
        currentP = boundaryPointSet(1,:);
        
        %Create a space smoothPointsSet  to store the point
        smoothPointsSet = NaN*ones(length(boundaryPointSet),2);
        %delete the current point from the boundaryPointSet
        boundaryPointSet(1,:) = [];
        ptsNum = 1; %record the number of smoothPointsSet
        
        smoothPointsSet(ptsNum,:) = currentP;

        while ~isempty(boundaryPointSet)
            %ultilize the built-in knnsearch() to 
            %achieve the nearest point of current point
            nearestPidx = knnsearch(boundaryPointSet,currentP);
            currentP = boundaryPointSet(nearestPidx,:);
            ptsNum = ptsNum + 1;
            smoothPointsSet(ptsNum,:) = currentP;
            %delete the nearest point from boundaryPointSet
            boundaryPointSet(nearestPidx,:) = [];
        end
        %visualize the smooth boundary
        plot(smoothPointsSet(:,1),smoothPointsSet(:,2))
        axis equal
    end

虽然findSmoothBoundary()可以正确找到平滑边界,但是效率却(关于数据,请看here


所以我想知道:

  • 如何高效求离散点阶?

数据

theta = linspace(0,2*pi,1000)';
boundaryPointSet= [2*sin(theta),cos(theta)];

tic;
findSmoothBoundary(boundaryPointSet)
toc;

%Elapsed time is 4.570719 seconds.

【问题讨论】:

  • 你的身材能有多奇怪?我可以假设质心包含在其中吗? (如果是,我有一个计算时间约为 0.2 秒的答案)
  • @BillBokeey 这个边界来自一系列部分。喜欢this

标签: performance matlab nearest-neighbor boundary


【解决方案1】:

这个答案并不完美,因为我必须做出一些假设才能让它发挥作用。但是,对于绝大多数情况,它应该按预期工作。此外,从您在 cmets 中提供的链接来看,我认为这些假设至少很弱,如果没有通过定义验证:

1.该点形成一个单一的连通区域

2。您的点的质心位于这些点的凸包中


如果这些假设得到尊重,您可以执行以下操作(完整代码在末尾):

第 1 步:计算点的质心

Means=mean(boundaryPointSet);

第 2 步:更改变量以将原点设置为质心

boundaryPointSet(:,1)=boundaryPointSet(:,1)-Means(1);
boundaryPointSet(:,2)=boundaryPointSet(:,2)-Means(2);

第三步:将坐标转换为极坐标

[Angles,Radius]=cart2pol(boundaryPointSet(:,1),boundaryPointSet(:,2));

Step4:Angle进行排序,并使用此排序对Radius进行排序

[newAngles,ids]=sort(Angles);
newRadius=Radius(ids);

Step5:回到笛卡尔坐标,重新添加质心坐标:

[X,Y]=pol2cart(newAngles,newRadius);
X=X+Means(1);
Y=Y+means(2);

完整代码

%%% Find smooth boundary
fid=fopen('SmoothBoundary.txt');
A=textscan(fid,'%f %f','delimiter',',');

boundaryPointSet=cell2mat(A);

boundaryPointSet(any(isnan(boundaryPointSet),2),:)=[];

idx=randperm(size(boundaryPointSet,1));

boundaryPointSet=boundaryPointSet(idx,:);

tic

plot(boundaryPointSet(:,1),boundaryPointSet(:,2))

%% Find mean value of all parameters

Means=mean(boundaryPointSet);

%% Center values around Mean point

boundaryPointSet(:,1)=boundaryPointSet(:,1)-Means(1);
boundaryPointSet(:,2)=boundaryPointSet(:,2)-Means(2);

%% Get polar coordinates of your points

[Angles,Radius]=cart2pol(boundaryPointSet(:,1),boundaryPointSet(:,2));

[newAngles,ids]=sort(Angles);
newRadius=Radius(ids);

[X,Y]=pol2cart(newAngles,newRadius);
X=X+Means(1);
Y=Y+means(2);    
toc

figure

plot(X,Y);

注意:由于您的值已经在您的输入文件中排序,我不得不通过排列它们来搞乱它

输出:

边界

经过的时间是 0.131808 秒。

输入错误:

输出:

【讨论】:

  • 非常感谢。关于假设 1,它成立。我将与其他case tommorow 一起测试您的想法:) 无论如何,将边界连接 问题转换为 坐标到极坐标 非常好。 Here 也是 Mathematica 的内置 ListCurvePathPlot 的解决方案。
  • 我看到你接受了@ShutaoTANG 的答案,它适用于你所有的测试用例吗?
  • 是的,@BillBokeey,我已经在很多情况下测试了你的想法,比如this,效果很好。:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-12
相关资源
最近更新 更多