2017-05-01 2 views
1

Je veux lisser le signal Sharkfin au point où elle descend et au point où il monte. Comme le montre la figure ci-dessous, la forme d'onde Sharkfin a forte baisse et hausse au temps 2 sec et 4 secondes:Lisser un angle aigu dans une fonction Matlab

As shown in the figure below, the Sharkfin waveform has sharp fall and rise at time 1 sec and 2 seconds

Toute idée sur la façon de tour de cette zone afin qu'elle soit lisse dans cette section si qu'il ressemble à ceci:

Smooth corner

+0

Vous cherchez un algorithme pour détecter forte coins dans un signal et les arrondir. En avez-vous trouvé un? – Anthony

+0

Notez que votre utilisation de ['convex'] (https://en.wikipedia.org/wiki/Convex_function) est probablement erronée. Lisser le coin ne le rendra pas plus convexe. – m7913d

+0

Plus qu'un algorithme, une étape suffit. J'ai une idée d'un filtre de moyenne mobile autour de la forte hausse et la chute pourrait fonctionner. Mais je cherchais de l'aide d'ici. Ou un peu d'aide dans la mise en œuvre du filtre uniquement sur une petite section de la courbe. –

Répondre

1

il y a deux choses distinctes ici - comment détecter une transition forte, et comment le filtre ne vous il.

Prenons ces éléments.

une transition nette se caractérise par une grande courbure - on peut facilement détecter ceci en prenant la diff de la courbe d'entrée. L'utilisation du deuxième paramètre = 2 prend deux fois diff et donne quelque chose de «semblable» à la dérivée seconde - mais elle est décalée d'une unité. Donc, quand nous trouvons des points où le diff(sharkfin,2) est grand, nous devons compenser par 1 pour obtenir les points de coin.

Ensuite, le lissage lui-même. Il y a beaucoup de techniques - je montre une convolution simple avec une fonction de boîte. Faire cela deux fois donne une version lissée de l'entrée. En choisissant l'original "loin de la discontinuité" et la version filtrée "proche de la discontinuité" nous obtenons exactement ce que vous demandiez. Si vous le souhaitez, vous pouvez "fusionner" les points - en utilisant une version pondérée de filtrée et non filtrée en fonction de la proximité des points d'angle. Je ne montre pas que explicitement mais il devrait être facile de voir comment développer le code je l'ai déjà écrit:

% 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' 

Sortie:

enter image description here

+0

Merci beaucoup pour cette réponse. J'ai modifié et utilisé en conséquence. Fonctionne vraiment bien :) –