如何在 MATLAB 中绘制通过大多数给定点的完美直线?
How to draw perfect straight line passing through majority of given points in MATLAB?
有人能帮我弄清楚如何从给定的点集通过这些点中的大多数(可能是 20 个点中的 5-6 个点)绘制一条完美的直线吗?请注意,这不是线拟合问题,而是应该在大多数给定点之间绘制完美的线(水平、垂直或稍微倾斜)。
这是 MATLAB 代码:
e=[161 162 193 195 155 40 106 102 125 155 189 192 186 188 185 186 147 148 180 183];
f =[138 92 92 115 258 124 218 114 125 232 431 252 539 463 643 571 582 726 726 676];
figure;scatter(f, e, 5, 'red');
axis ij;
这是图片:
一个简单但不是很有效的解决方案是计算每两个点之间的斜率,如果一组点位于一条直线上,则这些点的所有对都将具有相同的斜率。因此,一种算法可以选择所有具有相同斜率的点,如果它们有一个共同点,则将它们连接起来。最后你必须选择最大的一组。该算法的时间复杂度为 O(N^2 log N),其中 N 是点数。
正如我在你的图中看到的那样,并没有一条真正完美的线穿过所有的点,而是有一个公差,在这个算法中可以定义为连接两对的标准。比如说,如果两个斜率的差异小于 2%,我们就将它们连接起来。
由于您希望直线通过大部分点,因此听起来很像直线拟合问题,尽管您说不是。您是否看过 Theil-Sen 估计量 (for example this one on fex),这是一个线性回归,忽略了大约 30% 的异常值。
如果你只是想要一条穿过极值的线,你可以这样做:
% Setup data
e = [161 162 193 195 155 40 106 102 125 155 189 192 186 188 185 186 147 148 180 183];
f = [138 92 92 115 258 124 218 114 125 232 431 252 539 463 643 571 582 726 726 676];
% Create scatterplot
figure(1);
scatter(f, e, 5, 'red');
axis ij;
% Fit extrema
[min_e, min_idx_e] = min(e);
[max_e, max_idx_e] = max(e);
[min_f, min_idx_f] = min(f);
[max_f, max_idx_f] = max(f);
% Determine largest range and draw line accordingly
if (max_e-min_e)>(max_f-min_f)
line(f([min_idx_e, max_idx_e]), e([min_idx_e, max_idx_e]), 'color', 'blue')
text(f(max_idx_e), e(max_idx_e), ' Extrema')
else
line(f([min_idx_f, max_idx_f]), e([min_idx_f, max_idx_f]), 'color', 'blue')
text(f(max_idx_f), e(max_idx_f), ' Extrema')
end
% Fit using Theil-Sen estimator
[m, e0] = Theil_Sen_Regress(f', e');
line([min_f, max_f], m*[min_f, max_f]+e0, 'color', 'black')
text(max_f, m*max_f+e0, ' Theil-Sen')
但是,正如您会注意到的那样,这两种解决方案都不会自动拟合这些点,这仅仅是因为异常值太多,除非您事先过滤掉这些异常值。因此,您最好使用 Shai 和 McMa 提出的 RANSAC 算法。
这是 RANSAC algorithm. This free toolbox for Matlab 的教科书示例,实际上有一些非常好的线拟合示例。
有人能帮我弄清楚如何从给定的点集通过这些点中的大多数(可能是 20 个点中的 5-6 个点)绘制一条完美的直线吗?请注意,这不是线拟合问题,而是应该在大多数给定点之间绘制完美的线(水平、垂直或稍微倾斜)。
这是 MATLAB 代码:
e=[161 162 193 195 155 40 106 102 125 155 189 192 186 188 185 186 147 148 180 183];
f =[138 92 92 115 258 124 218 114 125 232 431 252 539 463 643 571 582 726 726 676];
figure;scatter(f, e, 5, 'red');
axis ij;
这是图片:
一个简单但不是很有效的解决方案是计算每两个点之间的斜率,如果一组点位于一条直线上,则这些点的所有对都将具有相同的斜率。因此,一种算法可以选择所有具有相同斜率的点,如果它们有一个共同点,则将它们连接起来。最后你必须选择最大的一组。该算法的时间复杂度为 O(N^2 log N),其中 N 是点数。 正如我在你的图中看到的那样,并没有一条真正完美的线穿过所有的点,而是有一个公差,在这个算法中可以定义为连接两对的标准。比如说,如果两个斜率的差异小于 2%,我们就将它们连接起来。
由于您希望直线通过大部分点,因此听起来很像直线拟合问题,尽管您说不是。您是否看过 Theil-Sen 估计量 (for example this one on fex),这是一个线性回归,忽略了大约 30% 的异常值。
如果你只是想要一条穿过极值的线,你可以这样做:
% Setup data
e = [161 162 193 195 155 40 106 102 125 155 189 192 186 188 185 186 147 148 180 183];
f = [138 92 92 115 258 124 218 114 125 232 431 252 539 463 643 571 582 726 726 676];
% Create scatterplot
figure(1);
scatter(f, e, 5, 'red');
axis ij;
% Fit extrema
[min_e, min_idx_e] = min(e);
[max_e, max_idx_e] = max(e);
[min_f, min_idx_f] = min(f);
[max_f, max_idx_f] = max(f);
% Determine largest range and draw line accordingly
if (max_e-min_e)>(max_f-min_f)
line(f([min_idx_e, max_idx_e]), e([min_idx_e, max_idx_e]), 'color', 'blue')
text(f(max_idx_e), e(max_idx_e), ' Extrema')
else
line(f([min_idx_f, max_idx_f]), e([min_idx_f, max_idx_f]), 'color', 'blue')
text(f(max_idx_f), e(max_idx_f), ' Extrema')
end
% Fit using Theil-Sen estimator
[m, e0] = Theil_Sen_Regress(f', e');
line([min_f, max_f], m*[min_f, max_f]+e0, 'color', 'black')
text(max_f, m*max_f+e0, ' Theil-Sen')
但是,正如您会注意到的那样,这两种解决方案都不会自动拟合这些点,这仅仅是因为异常值太多,除非您事先过滤掉这些异常值。因此,您最好使用 Shai 和 McMa 提出的 RANSAC 算法。
这是 RANSAC algorithm. This free toolbox for Matlab 的教科书示例,实际上有一些非常好的线拟合示例。