Как различать двойной пик и одиночную пиковую матрицу в MATLAB?

enter image description here

Как различать двойной пик и одиночную пиковую матрицу?

Также, если массив представляет двойной пик, как найти минимальную точку между двумя пиками? Минимальные точки за пределами пиков (слева от левого пика и справа от правого пика) не должны учитываться при поиске точки минимума.

Ответы

Ответ 1

Я нашел 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

Ответ 2

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

Предполагая, что исходные данные находятся в массиве A. Сначала найдите порог:

t = (max(A)+min(A))/2;

Затем найдите все точки, превышающие этот порог t:

P = A>t;

Подсчитайте количество подключенных точек входа, большее, чем t, используя bwlabel

L = bwlabel(P);
numberOfPeaks = max(L);

Теперь numberOfPeaks должен сказать вам, сколько пиков (связанных точек больше порогового значения) у вас есть в ваших данных

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

firstPoint = find(L==1,1,'last')+1;
lastPoint  = find(L==2,1,'first')-1;

Таким образом, долина между первыми двумя вершинами - это точки с индексом между firsPoint и lastPoint. Тогда минимум будет

minValue = min(A(firstPoint:lastPoint));

Решение, не зависящее от инструментария обработки изображений

Как отмечает @Nzbuu, aboth полагается на функцию bwlabel инструмента обработки изображений. Итак, здесь далеко, чтобы этого избежать. Сначала предположим, что массив P правильно идентифицирует точки, принадлежащие пику (P (i) = 1), и те, которые принадлежат долинам (P (i) = - 1). Если это так, то граница между пиками и долинами может быть идентифицирована при dP = P(i+1)-P(i) = 1 или -1.

dP = diff(P);

Чтобы вычислить количество пиков, просто суммируйте число 1 в dP:

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

Ответ 3

Вы можете найти локальный 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 меняет знаки. Если ваши данные шумные, это приведет к множеству локальных значений min/max, и вам может понадобиться отфильтровать ваши данные.

Чтобы найти минимальное значение между двумя пиками, вы можете сделать что-то вроде этого:

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