поиск пиков, которые имеют некоторую структуру в 1-d

#matlab #signal-processing

#matlab #обработка сигналов

Вопрос:

У меня есть сигнал с пиками, который имеет некоторую структуру поверх некоторого фона, и я пытаюсь найти надежный способ определения их положения и амплитуд.

Например, предположим, что пик имеет такую форму:

 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 .

Комментарии:

1. Вопрос не очень ясен. Какой пик вы считаете тем, на который вы хотите, чтобы ваш алгоритм указывал?

2. все они имеют 4 положения пиков, указанные в pos векторе.

3. findpeaks уже существует.

4. если я вас правильно понимаю, здесь произойдет сбой в случаях, когда амплитуда пика изменяется, потому что она не предполагает структуры, а только локальные максимумы. Здесь у пика есть особая функция, которая его генерирует. больше, чем просто локальные максимумы. в результате, когда пики близки, структура начнет искажать их максимумы. как видно на графике.

5. Мне интересно, будет ли этот вопрос более подходящим для переполнения стека цифровой обработки сигналов, dsp.stackexchange.com

Ответ №1:

Ваш сигнал можно рассматривать как свертку последовательности импульсов с формой пика. Деконволюция может быть использована для извлечения последовательности импульсов, пики которых являются местоположениями, которые вы ищете. Это предполагает, что форма пика известна и постоянна.

Я начну с переписывания вашего кода следующим образом:

 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 на take t-t0 , а не просто t0 . Это позволит мне позже создать чистый сигнал только с одним пиком в середине. Я также добавил шум к сигналу для более реалистичной задачи. Без шума проблему решить намного проще.

Деконволюция Винера — самый простой подход к решению этой проблемы. Короче говоря, мы предполагаем, что

 total_signal = conv(pulse_train, shape)
  

В частотной области это записывается как

 G = F .* H
  

.* поэлементным умножением, используя синтаксис 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)
  

вывод, показывающий 4 обнаруженных пика, близких к одинаковой высоте

Обратите внимание, что четыре пика имеют примерно одинаковую высоту. Это не точно, потому что мы упорядочиваем работу с шумом. Точное решение возможно только в случае отсутствия шума. Без шума, k=0 и выражение упрощается до F = G ./ H .

Кроме того, ось x отключена на графике, созданном findpeaks , но это не должно повлиять на результаты. Местоположения, возвращаемые им, являются индексами в массиве, эти же индексы можно использовать для индексации в t и нахождения фактических местоположений пиков.

Комментарии:

1. спасибо за подробный ответ! почему я получаю эти «ряби» вокруг пиков? есть ли способ их минимизировать?

2. @dpdp: Это вызвано шумом и регуляризацией. Поиграйте с k параметром, увеличьте его, чтобы уменьшить пульсации, но также и снизить пиковое качество.