【问题标题】:Finding peaks MATLAB寻找峰值 MATLAB
【发布时间】:2015-02-10 12:41:51
【问题描述】:

我有一个向量,其中包括图像的一行中的像素灰度级。 vec=IM(:,65); 我展示了我想要检测的数组部分。这些部分将成为我的对象的像素。

如何检测这些对象像素?

vec 的图: 向量在这里: vec

【问题讨论】:

  • 你试过findpeaks-方法了吗?它有要过滤的参数,我会先尝试“MinPeakprominence”
  • 同意丹尼尔。在数据的负数上使用findpeaks
  • 没人写的话我会尽快写答案
  • 你为什么改问题??
  • @MendiBarel 我把它恢复了。我讨厌人们这样做。我们的答案不再有意义,这是在他们也接受答案之后。

标签: matlab image-processing signal-processing


【解决方案1】:

这可以使用信号处理工具箱中的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.');

原始数据以蓝色绘制,而检测到的峰以红色绘制。这是我得到的:


祝你好运!

【讨论】:

  • @rayryend 好主意。为此+1。但是一个问题:为什么不 findpeaks(-vec, 'minpeakdistance', 160, 'minpeakheight', 22);为什么需要 max(vec)-vec?
  • @lakesh - 执行-vec 将否定数据的所有值,而minpeakheight 仅适用于 值。如果数据以零为中心,那么-vec 会起作用,但请注意所有点都高于 0。如果您尝试您的建议,您将收到一条警告,说明我所说的内容,并且您不会发现任何峰值。
  • @lakesh - 我的荣幸。继续问你是否感到困惑!
【解决方案2】:

找到局部峰值有不同的方法,这里我使用与局部平均值的偏差,然后分离区域,并扫描每个区域的最小值。

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

希望这有帮助, 门迪

【讨论】:

  • 你能告诉我们在给定 OP 数据的情况下使用你的算法会产生什么结果吗?它能否找到那些峰值并且 OP 示例中给出的那些峰值?从您的代码来看,它会找到所有局部峰值,但不会隔离 OP 指定的所需峰值
  • 非常好!好工作。但是,我确实觉得它很麻烦,因为您必须下载一个不属于本机 MATLAB 的额外文件。
  • 好的,我删除了外部文件并添加了移动平均滤波器的代码。
  • 移动平均线的 for 循环,我快死了……不,拜托,它会玷污你的解决方案。改用类似的东西:smooth_a = conv(a,ones(SMOOTH_SIZE,1)/SMOOTH_SIZE,'same');,更好更清晰。
  • 它给了我很好的结果,谢谢。一个问题,你是如何确定“THRESHOLD=0.7*std_a;”行中的数字 0.7 的?
猜你喜欢
  • 1970-01-01
  • 2017-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-28
  • 2017-02-22
  • 2014-09-23
相关资源
最近更新 更多