2012-01-05 54 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