您可以使用信号处理工具箱中的findpeaks
轻松解决此问题。具体来说,对于您的数据,我需要以如下方式调用它:
[pks, locs] = findpeaks(max(vec)-vec, 'minpeakdistance', 160, 'minpeakheight', 22);
findpeaks
只能找到正峰(局部最大值)。因此,我们需要反转它,使所有的局部极小值变成局部极大值。我通过取向量的最大值并将其减去向量来实现这一点。由于有很多局部峰值,minpeakdistance
字段允许您查找至少在每个峰值之间分隔这么多的峰值。我将其调整为160。此外,最小峰值高度查找大于某个数的峰值,我将其调整为22。 pks
找到实际峰值,而locs
给出信号中峰值的位置。我们需要使用locs
来找到实际的峰值数据,因为我们是在信号的镜像反射版本上执行的操作。因此,要获取实际的峰值数据,请执行以下操作:pks_final = vecs(loc);
findpeaks
定位的峰值绘制出来:plot(1:numel(vec), vec, locs, vec(locs), 'r.');
原始数据以蓝色绘制,而检测到的峰值以红色绘制。这是我得到的结果:
祝你好运!
-vec
会将数据的所有值取反,而minpeakheight
仅适用于正数。如果数据以零为中心,则-vec
将起作用,但请注意,所有点都在0上方。如果您尝试执行您的建议,您将收到一个警告,指明我所说的内容,并且您将找不到峰值。 - rayryeng寻找本地峰值的方法有多种,这里我使用与本地平均值的偏差来寻找,然后分离区域,并扫描每个区域的最小值。
clear
close all
load a
std_a=std( a(a~=0) );
SMOOTH_SIZE=131;% depend on data size
THRESHOLD=0.7*std_a;
smooth_a = conv(a,ones(SMOOTH_SIZE,1)/SMOOTH_SIZE,'same'); %ma filter
deviation_a=a-smooth_a;
negdev_a=deviation_a.*(deviation_a<-THRESHOLD); %deviation in negative region (minimum)
negdev_a_left=[negdev_a(2:end) 0]; % helper to find starting index point
negdev_a_right=[0 negdev_a(1:end-1)]; % helper to find end index point
negdev_a(1)=0; negdev_a(end)=0; % make sure that we have zero point
indfrom=find(negdev_a==0 & negdev_a_left~=0); %start index per region
indto=find(negdev_a==0 & negdev_a_right~=0); %start index per region
if(length(indfrom)~=length(indto)), error('error in regions');end
peak_indexes=zeros(1,length(indfrom)); %number of regions
peak_counter = 0;
for i=1:length(indfrom)
[center_min, min_idx]=min( a( indfrom(i):indto(i) ) );
real_min_idx=indfrom(i)-1+min_idx; % convert back to original array index
if( real_min_idx==indfrom(i) || real_min_idx==indto(i) ), continue; end
left_max=max(a( indfrom(i):real_min_idx-1)); %helper to check for real minimum
right_max=max(a( real_min_idx+1:indto(i))); %helper to check for real minimum
if(center_min<left_max && center_min<right_max) % check if this is real minimum
peak_counter=peak_counter+1;
peak_indexes(peak_counter)=real_min_idx;
end
% if you need subpixel accuracy you can do some weighted average in the min region
end
peak_indexes=peak_indexes(1:peak_counter); %narrow to found indexes
figure; plot(a); hold on; plot(smooth_a, 'k'); hold off;
figure; plot(deviation_a);hold on; plot(negdev_a,'r.');hold off;
figure; plot(a);hold on; plot(peak_indexes, a(peak_indexes),'rO');hold off; %result
希望这能有所帮助,
Mendi
smooth_a = conv(a,ones(SMOOTH_SIZE,1)/SMOOTH_SIZE,'same');
,更好更清晰。 - Bentoy13
findpeaks
方法吗?它有过滤参数,我建议先尝试使用'MinPeakprominence'。 - Danielfindpeaks
函数。 - rayryeng