这里有两件不同的事情 - 如何检测急剧过渡,以及如何过滤它。
让我们依次来看看。
急剧过渡的特点是曲率大 - 我们可以通过输入曲线的diff 轻松检测到这一点。使用第二个参数 = 2 需要两次 diff 并导致“类似于”二阶导数 - 但它偏移了一个。所以当我们找到diff(sharkfin,2)较大的点时,需要偏移1才能得到角点。
接下来,平滑本身。有很多技术——我展示了一个带有盒子函数的简单卷积。这样做两次会给出输入的平滑版本。通过选择原始的“远离不连续性”和过滤后的版本“接近不连续性”,我们得到了你所要求的。如果您愿意,您可以“混合”这些点 - 根据您与角点的接近程度,使用过滤和未过滤的加权版本。我没有明确显示,但应该很容易看出如何扩展我已经编写的代码:
% generate a "shark fin" function:
fin = exp(-linspace(0,4,60));
shark = [fin (1-fin+fin(end))];
shark = repmat(shark, [1 3]);
D2 = diff(shark, 2);
roundMe = find(abs(D2)>0.1*max(D2))+1; % offset by 1 because second derivative
figure;
subplot(3,1,1)
plot(shark); title 'shark plot'
hold on;
plot(roundMe, shark(roundMe),'r*')
legend('input','corners found')
% take N points on either side of the sharp corners:
N = 3;
% boxplot filtered version of the curve
boxFilt = ones(1, 2*N+1)/(2*N+1);
smoothShark1 = convn(shark, boxFilt, 'same'); % box plot
% second filter - smoother
smoothShark2 = convn(smoothShark1, boxFilt, 'same');
% plot the filtered results:
subplot(3,1,2)
plot(shark)
hold on
plot(smoothShark1);
hold on
plot(smoothShark2);
xlim([114 126])
ylim([0.8,1.1])
legend('original','box','box x2')
title 'smoothed everywhere'
% Now apply filtering only to points near the discontinuity
smoothMe = zeros(size(shark));
smoothMe(roundMe)=1;
smoothMe = convn(smoothMe, boxFilt, 'same');
smoothMe(smoothMe>0)=1; % this finds N points on either side of the corner
subplot(3,1,3)
plot(shark)
finalPlot=shark;
hold on
smoothIndx = find(smoothMe);
finalPlot(smoothIndx)=smoothShark2(smoothIndx);
plot(finalPlot,'g')
plot(smoothIndx, finalPlot(smoothIndx), 'r*')
xlim([114 126])
ylim([0.8,1.1])
legend('original','smoothed','changed')
title 'smoothed only near discontinuity'
输出: