2012-01-05 191 views
12

enter image description here如何區分MATLAB中的雙峯和單峯陣列?

如何區分雙峯和單峯陣列?

此外,如果數組表示一個雙峯值,如何找到兩個峯值之間的最小點?找到最小點時,不應考慮峯外側的最小點(左側峯值的左側和右側峯值的右側)。

+0

@Nzbuu:這與信號處理的事情。並非所有信號都是圖像。 – Jonas 2012-01-06 19:01:06

回答

8

我發現PEAKDET功能是相當可靠和快速的,雖然它是基於循環。它不需要預先平滑噪聲數據,但會發現局部最大和最小極值,其差值大於參數delta

由於PEAKDET從左到右運行,有時會錯過右側站點的峯值。爲了避免它,我寧願兩次運行:

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

謝謝,PEAKDET是一種很好的方法。一個缺點 - 它從凸極值開始搜索。 – 23W 2013-03-26 09:34:25

+0

@yuk參數delta在peakdet中做什麼 – kkk 2015-12-30 19:08:31

+0

基本上,delta參數設置您想要忽略的波動幅度。嘗試改變它,看看它會如何影響結果。 – yuk 2016-01-03 00:52:53

8

下面是一種算法,可能工作取決於你的信號有多嘈雜。在這裏,我定義一個峯值作爲大於給定閾值的連接點集。

假設您的原始數據在陣列中A。首先,找到閾值:

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

接着,找到所有大於該閾值的點

P = A>t; 

計數數是大於使用bwlabel

連接的條目點
L = bwlabel(P); 
numberOfPeaks = max(L); 

現在numberOfPeaks應告訴您數據中有多少個峯(連接點大於閾值)

現在要找到兩個峯之間的最小點,我們需要確定那些使用標記矩陣分離兩個峯的點L

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

所以前兩個波峯之間的波谷是firsPointlastPoint之間的指數點。然後最小將是

不依賴於圖像處理工具箱

作爲@Nzbuu注意到aboth依賴於圖像處理工具箱功能bwlabel

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

解。所以,這是爲了避免這種情況。首先,假設陣列P正確識別屬於峯值的點(P(i)= 1)和屬於谷值的點(P(i)= - 1)。如果是這種情況,則可以在dP = P(i+1)-P(i) = 1-1時識別峯和谷之間的邊界。

dP = diff(P); 

要計算峯值的數量簡單地合計在dP 1點的數量:

numberOfPeaks = sum(dP==1); 

以及標識第一谷點

之間
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

我認爲不使用圖像處理工具箱的解決方案會更有用。 – Nzbuu 2012-01-06 00:17:29

+0

@Nzbuu我同意並添加了第二種方法。 – Azim 2012-01-06 17:27:31

5

您可以找到當地的min/max如下:

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

產生於: enter image description here

基本上你會發現y值之間的增量變化的跡象。如果您的數據嘈雜,則會導致大量本地最小/最大值,您可能需要過濾數據。

找到兩個峯值間的最小值,你可以做這樣的事情:

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

一般來說,我會去做這樣的事情,但是如果你想避免影響結果的噪音,你可能需要在使用之前平滑你的數據。 – Nzbuu 2012-01-06 00:16:17

+0

@Nzbuu同意,這就是爲什麼我有關於噪音的警告。解決方案將取決於數據集的特徵。也就是說,如果噪聲很大,您很可能必須首先應用濾波器,而信號/噪聲特性將決定需要哪種濾波器。 – 2012-01-06 00:43:32

+1

@Aero Engy,我想我錯過了:/仍然是爲了突出這一點。 – Nzbuu 2012-01-06 22:53:03