我目前正试图在MATLAB中通过分散数据的扩展拟合线性线。现在这很容易使用polyfit函数,我可以很容易地获得我的y = mx + c等式。但是,我现在需要沿着数据的上边界拟合一条线,即前几个数据点。我知道这个描述是模糊的,所以我们假设我的散射数据将呈锥形,其顶点位于y轴上,并且在+ x和+ y方向上向外和向上展开。如果愿意的话,我需要在“锥体的上边缘”上安装最合适的线条。
我开发了一种算法,但速度非常慢。它涉及首先通过ALL数据拟合最佳拟合线,删除该最佳拟合线下方的所有数据点,并迭代直到仅剩下5%的初始数据点。然后,最终的最佳拟合线将位于锥体的顶部边缘附近。对于250个数据点,这需要大约5秒,而且我处理了超过一百万个数据点,这个算法效率太低。
我想我的问题是:是否有一种算法可以更有效地实现我的需求?或者有没有办法增强我的代码以消除不必要的复杂性?
这是我在MATLAB中的代码:
(例如)
a = [4, 5, 1, 8, 1.6, 3, 8, 9.2]; %To be used as x-axis points
b = [45, 53, 12, 76, 25, 67, 75, 98]; %To be used as y-axis points
while prod(size(a)) > (0.05*prod(size(a))) %Iterative line fitting occurs until there are less than 5% of the data points left
lobf = polyfit(a,b,1); %Line of Best Fit for current data points
alen = length(a);
for aindex = alen:-1:1 %For loop to delete all points below line of best fit
ValLoBF = lobf(1)*a(aindex) + lobf(2)
if ValLoBF > b(aindex) %if LoBF is above current point...
a(aindex) = []; %delete x coordinate...
b(aindex) = []; %and delete its corresponding y coordinate
end
end
end
答案 0 :(得分:1)
首先,您的示例代码似乎无限期地运行;)
对您的代码进行一些优化:
a = [4, 5, 1, 8, 1.6, 3, 8, 9.2]; %To be used as x-axis points
b = [45, 53, 12, 76, 25, 67, 75, 98]; %To be used as y-axis points
n_init_a = length(a);
while length(a) > 0.05*n_init_a %Iterative line fitting occurs until there are less than 5% of the data points left
lobf = polyfit(a,b,1); % Line of Best Fit for current data points
% Delete data points below line using logical indexing
% First create values of the polyfit points using element-wise vector multiplication
temp = lobf(1)*a + lobf(2); % Containing all polyfit values
% Using logical indexing to discard all points below
a(b<temp)=[]; % First destroy a
b(b<temp)=[]; % Then b, very important!
end
您还应该尝试通过在命令窗口中输入
来分析代码profile viewer
并检查计算结果的时间最多。我怀疑它是polyfit但可能不会加速。
答案 1 :(得分:0)
您正在寻找的不是线条拟合。你试图找到点的凸包。
您应该查看函数convhull
。一旦找到船体,就可以移除所有不靠近它的点,并独立地适应每个部分,以避免数据嘈杂。
或者,您可以将点渲染到某个像素网格上,然后执行某种形态操作,如imclose
,并使用Hough变换完成。请查看此answer。