2012-01-05 10 views
12

enter image description hereCome distinguere tra un doppio picco e un singolo picco di array in MATLAB?

Come distinguere tra un picco doppio e un singolo array di picco?

Anche se l'array rappresenta un doppio picco, come trovare il punto minimo tra due picchi? I punti minimi al di fuori dei picchi (sinistra del picco sinistro e del picco destro) non dovrebbero essere considerati nel trovare il punto minimo.

+0

@Nzbuu: Questo ha a che fare con l'elaborazione del segnale. Non tutto il segnale è un'immagine. – Jonas

risposta

8

ho trovato PEAKDET funzione per essere molto affidabile e veloce, anche se basata Loop. Non richiede il livellamento dei dati rumorosi, ma trova gli estremi max e min locali con differenza maggiore del parametro delta.

Dal momento che PEAKDET va da sinistra a destra, a volte mancano i picchi sul sito giusto. Per evitare questo preferisco correre due volte:

%# some data 
n = 100; 
x = linspace(0,3*pi,n); 
y = sin(x) + rand(1,n)/5; 

%# run peakdet twice left-to-right and right-to-left 
delta = 0.5; 
[ymaxtab, ymintab] = peakdet(y, delta, x); 
[ymaxtab2, ymintab2] = peakdet(y(end:-1:1), delta, x(end:-1:1)); 
ymaxtab = unique([ymaxtab; ymaxtab2],'rows'); 
ymintab = unique([ymintab; ymintab2],'rows'); 

%# plot the curve and show extreme points based on number of peaks 
plot(x,y) 
hold on 
if size(ymaxtab,1) == 2 && size(ymintab,1) == 1 %# if double peak 
    plot(ymintab(:,1),ymintab(:,2),'r.','markersize',30) 
elseif size(ymaxtab,1) == 1 && size(ymintab,1) == 0 %# if single peak 
    plot(ymaxtab(:,1),ymaxtab(:,2),'r.','markersize',30) 
else %# if more (or less) 
    plot(ymintab(:,1),ymintab(:,2),'r.','markersize',30) 
    plot(ymaxtab(:,1),ymaxtab(:,2),'r.','markersize',30) 
end 
hold off 

Two peaks example

+0

Grazie, il PEAKDET è un buon approccio. Uno svantaggio: inizia le ricerche dall'estremo convesso. – 23W

+0

@yuk cosa fa il parametro delta do in peakdet – kkk

+0

Fondamentalmente il parametro delta imposta quale grandezza delle fluttuazioni si desidera ignorare. Prova a variare e vedere come influenzerà i risultati. – yuk

8

Ecco un algoritmo che potrebbe funzionare a seconda di quanto sia rumoroso il segnale. Qui definisco un picco come set di punti collegati maggiore di un dato valore di soglia.

Supponendo che i dati originali siano nell'array A. In primo luogo, per una soglia:

t = (max(A)+min(A))/2; 

Quindi, trovare tutti i punti superiori a questa soglia t: numero

P = A>t; 

conte di iscrizioni punti collegati che sono maggiori di t utilizzando bwlabel

L = bwlabel(P); 
numberOfPeaks = max(L); 

Ora numberOfPeaks dovrebbe dirvi quanti picchi (punti collegati maggiori del valore di soglia) che avete nei vostri dati

Ora per trovare il punto minimo tra i due picchi dobbiamo identificare quei punti che separano i due picchi usando la matrice di etichette L.

firstPoint = find(L==1,1,'last')+1; 
lastPoint = find(L==2,1,'first')-1; 

Quindi la valle tra i primi due picchi è punti con indice tra firsPoint e LASTPOINT. Il minimo sarebbe quindi

minValue = min(A(firstPoint:lastPoint)); 

Soluzione che non dipende Image Processing Toolbox

Come @Nzbuu osserva l'Aboth si basa sulla elaborazione dell'immagine funzione STRUMENTI bwlabel. Quindi, qui è via per evitarlo. Innanzitutto, suppongo che l'array P identifichi correttamente i punti appartenenti al picco (P (i) = 1) e quelli appartenenti alle valli (P (i) = - 1). In questo caso, è possibile identificare il limite tra i picchi e le valli quando dP = P(i+1)-P(i) = 1 o -1.

dP = diff(P); 

Per calcolare il numero di picchi semplicemente sommare il numero di 1 di in dP:

numberOfPeaks = sum(dP==1); 

E i punti che identificano la prima valle sono tra

firstPoint = find(dP==-1,1,'first')+1 %# the -1 represents the last point of the peak so add 1 
lastPoint = find(dP==1,2,'first'); #% Find the start of the second peak 
lastPoint = lastPoint(end); #% Keep the last value 
+0

Penso che una soluzione che non usa la toolbox per l'elaborazione delle immagini sarà più utile. – Nzbuu

+0

@ Nzbuu Ho concordato e aggiunto un secondo metodo. – Azim

5

È possibile trovare il locale min/max come segue:

x = 0:.1:4*pi; 
y = sin(x); 

plot(x,y) 

diffy = diff(y); 
localMin = find(diffy(1:end-1)<=0 & diffy(2:end) > 0)+1; 
localMax = find(diffy(1:end-1)>=0 & diffy(2:end) < 0)+1; 

hold on 
plot(x(localMin),y(localMin),'dg') 
plot(x(localMax),y(localMax),'*r') 

Con conseguente: enter image description here

Fondamentalmente si stanno trovando in cui il delta tra i valori y cambia segni. Se i tuoi dati sono disturbati, questo causerà molti valori min/max locali e potresti dover filtrare i tuoi dati.

per trovare il valore minimo tra due picchi si può fare qualcosa di simile:

if numel(localMax) == 1 
    fprintf('The max value is: %f',y(localMax)); 
elseif numel(localMax > 1) 
    betweenPeaksIndex = localMin(localMin > localMax(1) & localMin <localMax(2)); 
    fprintf('The min between the first 2 peaks is: %f',y(betweenPeaksIndex)); 
else 
    fprintf('The was no local Max ..???'); 
end 
+3

In generale, sceglierei qualcosa di simile, ma potrebbe essere necessario smussare i dati prima di usarli se si desidera evitare il rumore che influisce sul risultato. – Nzbuu

+0

@ Nzbuu D'accordo, è per questo che ho l'avvertenza per quanto riguarda il rumore. La soluzione dipenderà dalle caratteristiche del tuo set di dati. Se è rumoroso, molto probabilmente dovrai applicare prima un filtro e le caratteristiche segnale/rumore determineranno quale tipo di filtro è necessario. –

+1

@Aero Engy, credo di essermi perso:/Ancora, serve per evidenziare il punto. – Nzbuu

Problemi correlati