Matlab 如何将两条多边形拟合线从任意一侧延伸到相交处,并获得组合拟合线
我试图从两侧(应相交)的两个线性多边形拟合得到组合拟合线,以下是拟合线的图片: 我正在尝试使两条拟合(蓝色)线相交,并生成一条组合拟合线,如下图所示: 请注意,波峰可以发生在任何地方,所以我不能假设它在中心 以下是创建第一个绘图的代码:Matlab 如何将两条多边形拟合线从任意一侧延伸到相交处,并获得组合拟合线,matlab,curve-fitting,polynomial-math,line-intersection,linear-equation,Matlab,Curve Fitting,Polynomial Math,Line Intersection,Linear Equation,我试图从两侧(应相交)的两个线性多边形拟合得到组合拟合线,以下是拟合线的图片: 我正在尝试使两条拟合(蓝色)线相交,并生成一条组合拟合线,如下图所示: 请注意,波峰可以发生在任何地方,所以我不能假设它在中心 以下是创建第一个绘图的代码: xdatPart1 = R; zdatPart1 = z; n = 3000; ln = length(R); [sX,In] = sort(R,1); sZ = z(In); xdatP1 = sX(1:n,1); zdatP1 =
xdatPart1 = R;
zdatPart1 = z;
n = 3000;
ln = length(R);
[sX,In] = sort(R,1);
sZ = z(In);
xdatP1 = sX(1:n,1);
zdatP1 = sZ(1:n,1);
n2 = ln - 3000;
xdatP2 = sX(n2:ln,1);
zdatP2 = sZ(n2:ln,1);
pp1 = polyfit(xdatP1,zdatP1,1);
pp2 = polyfit(xdatP2,zdatP2,1);
ff1 = polyval(pp1,xdatP1);
ff2 = polyval(pp2,xdatP2);
xDat = [xdatPart1];
zDat = [zdatPart1];
axes(handles.axes2);
cla(handles.axes2);
plot(xdatPart1,zdatPart1,'.r');
hold on
plot(xdatP1,ff1,'.b');
plot(xdatP2,ff2,'.b');
xlabel(['R ',units]);
ylabel(['Z ', units]);
grid on
hold off
下面是一个没有曲线拟合工具箱的粗略实现。虽然代码应该是不言自明的,但下面是算法的概要:
ppfunc
,是一个1个变量的函数句柄,您可以像这样使用它function ppfunc = q40160257
%% Define the ground truth:
center_x = 6 + randn(1);
center_y = 78.15 + 0.01 * randn(1);
% Define a couple of points for the left section
leftmost_x = 0;
leftmost_y = 78.015 + 0.01 * randn(1);
% Define a couple of points for the right section
rightmost_x = 14.8;
rightmost_y = 78.02 + 0.01 * randn(1);
% Find the line equations:
m1 = (center_y-leftmost_y)/(center_x-leftmost_x);
n1 = getN(leftmost_x,leftmost_y,m1);
m2 = (rightmost_y-center_y)/(rightmost_x-center_x);
n2 = getN(rightmost_x,rightmost_y,m2);
% Print the ground truth:
fprintf(1,'The line equations are: {y1=%f*x+%f} , {y2=%f*x+%f}\n',m1,n1,m2,n2)
%% Generate some data:
NOISE_MAGNITUDE = 0.002;
N_POINTS_PER_SIDE = 1000;
x1 = linspace(leftmost_x,center_x,N_POINTS_PER_SIDE);
y1 = m1*x1+n1+NOISE_MAGNITUDE*randn(1,numel(x1));
x2 = linspace(center_x,rightmost_x,N_POINTS_PER_SIDE);
y2 = m2*x2+n2+NOISE_MAGNITUDE*randn(1,numel(x2));
X = [x1 x2(2:end)]; Y = [y1 y2(2:end)];
%% See what we have:
figure(); plot(X,Y,'.r'); hold on;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Estimating the intersection point:
MOVING_AVERAGE_PERIOD = 10; % Play around with this value.
smoothed_data = conv(Y, ones(1,MOVING_AVERAGE_PERIOD)/MOVING_AVERAGE_PERIOD, 'same');
plot(X, smoothed_data, '-b'); ylim([floor(leftmost_y*10) ceil(center_y*10)]/10);
[~,centerInd] = max(smoothed_data);
fprintf(1,'The real intersection is at index %d, the estimated is at %d.\n',...
N_POINTS_PER_SIDE, centerInd);
%% Fitting a polynomial to each side:
p1 = polyfit(X(1:centerInd),Y(1:centerInd),1);
p2 = polyfit(X(centerInd+1:end),Y(centerInd+1:end),1);
[x_int,y_int] = getLineIntersection(p1,p2);
plot(x_int,y_int,'sg');
pp = mkpp([X(1) x_int X(end)],[p1; (p2 + [0 x_int*p2(1)])]);
ppfunc = @(x)ppval(pp,x);
plot(X, ppfunc(X),'-k','LineWidth',3)
legend('Original data', 'Smoothed data', 'Computed intersection',...
'Final piecewise-linear fit');
grid on; grid minor;
%% Comparison with the curve-fitting toolbox:
if license('test','Curve_Fitting_Toolbox')
ft = fittype( '(x<=-(n2-n1)/(m2-m1))*(m1*x+n1)+(x>-(n2-n1)/(m2-m1))*(m2*x+n2)',...
'independent', 'x', 'dependent', 'y' );
opts = fitoptions( 'Method', 'NonlinearLeastSquares' );
% Parameter order: m1, m2, n1, n2:
opts.StartPoint = [0.02 -0.02 78 78];
fitresult = fit( X(:), Y(:), ft, opts);
% Comparison with what we did above:
fprintf(1,[...
'Our solution:\n'...
'\tm1 = %-12f\n\tm2 = %-12f\n\tn1 = %-12f\n\tn2 = %-12f\n'...
'Curve Fitting Toolbox'' solution:\n'...
'\tm1 = %-12f\n\tm2 = %-12f\n\tn1 = %-12f\n\tn2 = %-12f\n'],...
m1,m2,n1,n2,fitresult.m1,fitresult.m2,fitresult.n1,fitresult.n2);
end
%% Helper functions:
function n = getN(x0,y0,m)
% y = m*x+n => n = y0-m*x0;
n = y0-m*x0;
function [x_int,y_int] = getLineIntersection(p1,p2)
% m1*x+n1 = m2*x+n2 => x = -(n2-n1)/(m2-m1)
x_int = -(p2(2)-p1(2))/(p2(1)-p1(1));
y_int = p1(1)*x_int+p1(2);
围绕交叉点放大:
下面是一个没有曲线拟合工具箱的粗略实现。虽然代码应该是不言自明的,但下面是算法的概要:
ppfunc
,是一个1个变量的函数句柄,您可以像这样使用它function ppfunc = q40160257
%% Define the ground truth:
center_x = 6 + randn(1);
center_y = 78.15 + 0.01 * randn(1);
% Define a couple of points for the left section
leftmost_x = 0;
leftmost_y = 78.015 + 0.01 * randn(1);
% Define a couple of points for the right section
rightmost_x = 14.8;
rightmost_y = 78.02 + 0.01 * randn(1);
% Find the line equations:
m1 = (center_y-leftmost_y)/(center_x-leftmost_x);
n1 = getN(leftmost_x,leftmost_y,m1);
m2 = (rightmost_y-center_y)/(rightmost_x-center_x);
n2 = getN(rightmost_x,rightmost_y,m2);
% Print the ground truth:
fprintf(1,'The line equations are: {y1=%f*x+%f} , {y2=%f*x+%f}\n',m1,n1,m2,n2)
%% Generate some data:
NOISE_MAGNITUDE = 0.002;
N_POINTS_PER_SIDE = 1000;
x1 = linspace(leftmost_x,center_x,N_POINTS_PER_SIDE);
y1 = m1*x1+n1+NOISE_MAGNITUDE*randn(1,numel(x1));
x2 = linspace(center_x,rightmost_x,N_POINTS_PER_SIDE);
y2 = m2*x2+n2+NOISE_MAGNITUDE*randn(1,numel(x2));
X = [x1 x2(2:end)]; Y = [y1 y2(2:end)];
%% See what we have:
figure(); plot(X,Y,'.r'); hold on;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Estimating the intersection point:
MOVING_AVERAGE_PERIOD = 10; % Play around with this value.
smoothed_data = conv(Y, ones(1,MOVING_AVERAGE_PERIOD)/MOVING_AVERAGE_PERIOD, 'same');
plot(X, smoothed_data, '-b'); ylim([floor(leftmost_y*10) ceil(center_y*10)]/10);
[~,centerInd] = max(smoothed_data);
fprintf(1,'The real intersection is at index %d, the estimated is at %d.\n',...
N_POINTS_PER_SIDE, centerInd);
%% Fitting a polynomial to each side:
p1 = polyfit(X(1:centerInd),Y(1:centerInd),1);
p2 = polyfit(X(centerInd+1:end),Y(centerInd+1:end),1);
[x_int,y_int] = getLineIntersection(p1,p2);
plot(x_int,y_int,'sg');
pp = mkpp([X(1) x_int X(end)],[p1; (p2 + [0 x_int*p2(1)])]);
ppfunc = @(x)ppval(pp,x);
plot(X, ppfunc(X),'-k','LineWidth',3)
legend('Original data', 'Smoothed data', 'Computed intersection',...
'Final piecewise-linear fit');
grid on; grid minor;
%% Comparison with the curve-fitting toolbox:
if license('test','Curve_Fitting_Toolbox')
ft = fittype( '(x<=-(n2-n1)/(m2-m1))*(m1*x+n1)+(x>-(n2-n1)/(m2-m1))*(m2*x+n2)',...
'independent', 'x', 'dependent', 'y' );
opts = fitoptions( 'Method', 'NonlinearLeastSquares' );
% Parameter order: m1, m2, n1, n2:
opts.StartPoint = [0.02 -0.02 78 78];
fitresult = fit( X(:), Y(:), ft, opts);
% Comparison with what we did above:
fprintf(1,[...
'Our solution:\n'...
'\tm1 = %-12f\n\tm2 = %-12f\n\tn1 = %-12f\n\tn2 = %-12f\n'...
'Curve Fitting Toolbox'' solution:\n'...
'\tm1 = %-12f\n\tm2 = %-12f\n\tn1 = %-12f\n\tn2 = %-12f\n'],...
m1,m2,n1,n2,fitresult.m1,fitresult.m2,fitresult.n1,fitresult.n2);
end
%% Helper functions:
function n = getN(x0,y0,m)
% y = m*x+n => n = y0-m*x0;
n = y0-m*x0;
function [x_int,y_int] = getLineIntersection(p1,p2)
% m1*x+n1 = m2*x+n2 => x = -(n2-n1)/(m2-m1)
x_int = -(p2(2)-p1(2))/(p2(1)-p1(1));
y_int = p1(1)*x_int+p1(2);
围绕交叉点放大:
做了一些编辑以使其清晰明了。您需要估计的结果有多好。。。?我可以想出一个解决方案,但它在最小二乘法(或任何其他)意义上都不是最优的。。。另外,你有曲线拟合工具箱吗?没有,我没有曲线拟合工具箱。你能给出一个没有工具箱的解决方案吗?你做了一些编辑来弄清楚。你需要估计值有多好。。。?我可以想出一个解决方案,但它在最小二乘法(或任何其他)意义上都不是最优的。。。另外,你有曲线拟合工具箱吗?没有,我没有曲线拟合工具箱,请你给出一个没有工具箱的解决方案好吗?谢谢,先生,我理解大部分代码,但我在理解基本事实方面有困难。在我的情况下,两边都有部分数据,如何计算基本事实或中心。@nman84在您的案例中不需要这些数据。请注意,在拟合多项式之后,我的代码只依赖于拟合的方程-您也有。只需跳到我做的部分
getLineIntersection(p1,p2)代码>但使用您的pp1
pp2
。我之所以这样做,是因为我必须自己生成数据,并将其分为两部分,这两部分都是有意义的。您的数据没有这样的问题。谢谢先生,我理解了大部分代码,但我在理解基本事实方面遇到了困难。在我的情况下,两边都有部分数据,如何计算基本事实或中心。@nman84在您的案例中不需要这些数据。请注意,在拟合多项式之后,我的代码只依赖于拟合的方程-您也有。只需跳到我做的部分getLineIntersection(p1,p2)代码>但使用您的pp1
pp2
。我之所以这样做,是因为我必须自己生成数据,并将其分为两部分,这两部分都是有意义的。你的数据没有这样的问题。