在一维中找到具有某种结构的峰
finding peaks that have some structure in 1-d
我的峰值信号在某些背景之上具有某种结构,我正试图找到一种稳健的方法来定位它们的位置和幅度。
例如,假设峰具有这种形式:
t=linspace(0,10,1e3);
w=0.25;
rw=@(t0) 2/(sqrt(3*w)*pi^0.25)*(1-((t-t0)/w).^2).*exp(-(t-t0).^2/(2*w.^2));
我有几个峰太近了,所以它们的结构开始干扰其他峰,一个分开,所以你可以看到它的结构:
pos=[ 2 2.5 3 8]; % positions
total_signal=0.*t;
for i=1:length(pos)
total_signal=total_signal+rw(pos(i));
end
plot(t,total_signal);
所以目标是找到在 total_signal
中找到的所有峰,并检查它们的位置是否与用于在 pos
中生成它们的原始位置一致。
您的信号可以被认为是脉冲序列与峰形的卷积。反卷积可用于检索脉冲序列,其峰值就是您要查找的位置。这假设峰形已知且恒定。
我将从如下重写您的代码开始:
t = linspace(0,10,1e3);
w = 0.25;
rw = @(t) 2/(sqrt(3*w)*pi^0.25)*(1-((t)/w).^2).*exp(-(t).^2/(2*w.^2));
pos = [2, 2.5, 3, 8];
total_signal = zeros(size(t));
for i=1:length(pos)
total_signal = total_signal + rw(t-pos(i));
end
total_signal = total_signal + randn(size(t))*1e-2;
plot(t,total_signal);
我已经将 rw
改为 t-t0
,而不仅仅是 t0
。这将使我稍后可以创建一个干净的信号,中间只有一个峰值。我还为信号添加了噪声,以解决更现实的问题。没有噪音,问题就容易解决了。
Wiener deconvolution 是解决这个问题最简单的方法。简而言之,我们假设
total_signal = conv(pulse_train, shape)
在频域中,这写成
G = F .* H
(与 .*
相乘 element-wise,此处使用 MATLAB 语法)。维纳反卷积是:
F = (conj(H) .* G) ./ (abs(H).^2 + k)
使用 k
一些常数,我们可以调整这些常数以正则化解。
我们按如下方式实现:
shape = rw(linspace(-5,5,1e3));
G = fft(total_signal);
H = fft(ifftshift(shape)); % ifftshift moves the origin to sample #0, as expected by FFT.
k = 1;
F = (conj(H) .* G) ./ (abs(H).^2 + k);
pulse_train = ifft(F);
现在,findpeaks
(需要信号处理工具箱)可用于查找突出的峰值:
findpeaks(pulse_train, 'MinPeakProminence', 0.02)
注意四个峰的高度大致相同。这并不准确,因为我们正在规范化处理噪音。只有在 noise-free 情况下才可能有精确解。没有噪声,k=0
,表达式简化为F = G ./ H
.
此外,x-axis 在 findpeaks
生成的图中不存在,但这应该不会影响结果。它返回的位置是数组的索引,这些相同的索引可用于索引 t
并找到峰值的实际位置。
我的峰值信号在某些背景之上具有某种结构,我正试图找到一种稳健的方法来定位它们的位置和幅度。
例如,假设峰具有这种形式:
t=linspace(0,10,1e3);
w=0.25;
rw=@(t0) 2/(sqrt(3*w)*pi^0.25)*(1-((t-t0)/w).^2).*exp(-(t-t0).^2/(2*w.^2));
我有几个峰太近了,所以它们的结构开始干扰其他峰,一个分开,所以你可以看到它的结构:
pos=[ 2 2.5 3 8]; % positions
total_signal=0.*t;
for i=1:length(pos)
total_signal=total_signal+rw(pos(i));
end
plot(t,total_signal);
所以目标是找到在 total_signal
中找到的所有峰,并检查它们的位置是否与用于在 pos
中生成它们的原始位置一致。
您的信号可以被认为是脉冲序列与峰形的卷积。反卷积可用于检索脉冲序列,其峰值就是您要查找的位置。这假设峰形已知且恒定。
我将从如下重写您的代码开始:
t = linspace(0,10,1e3);
w = 0.25;
rw = @(t) 2/(sqrt(3*w)*pi^0.25)*(1-((t)/w).^2).*exp(-(t).^2/(2*w.^2));
pos = [2, 2.5, 3, 8];
total_signal = zeros(size(t));
for i=1:length(pos)
total_signal = total_signal + rw(t-pos(i));
end
total_signal = total_signal + randn(size(t))*1e-2;
plot(t,total_signal);
我已经将 rw
改为 t-t0
,而不仅仅是 t0
。这将使我稍后可以创建一个干净的信号,中间只有一个峰值。我还为信号添加了噪声,以解决更现实的问题。没有噪音,问题就容易解决了。
Wiener deconvolution 是解决这个问题最简单的方法。简而言之,我们假设
total_signal = conv(pulse_train, shape)
在频域中,这写成
G = F .* H
(与 .*
相乘 element-wise,此处使用 MATLAB 语法)。维纳反卷积是:
F = (conj(H) .* G) ./ (abs(H).^2 + k)
使用 k
一些常数,我们可以调整这些常数以正则化解。
我们按如下方式实现:
shape = rw(linspace(-5,5,1e3));
G = fft(total_signal);
H = fft(ifftshift(shape)); % ifftshift moves the origin to sample #0, as expected by FFT.
k = 1;
F = (conj(H) .* G) ./ (abs(H).^2 + k);
pulse_train = ifft(F);
现在,findpeaks
(需要信号处理工具箱)可用于查找突出的峰值:
findpeaks(pulse_train, 'MinPeakProminence', 0.02)
注意四个峰的高度大致相同。这并不准确,因为我们正在规范化处理噪音。只有在 noise-free 情况下才可能有精确解。没有噪声,k=0
,表达式简化为F = G ./ H
.
此外,x-axis 在 findpeaks
生成的图中不存在,但这应该不会影响结果。它返回的位置是数组的索引,这些相同的索引可用于索引 t
并找到峰值的实际位置。