Как различать двойной пик и одиночную пиковую матрицу в 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