ダブルピークアレイとシングルピークアレイを区別する方法は?
また、配列が二重ピークを表す場合、2 つのピーク間の最小点を見つける方法は? ピークの外側の最小点 (左側のピークの左側と右側のピークの右側) は、最小点を見つける際に考慮されるべきではありません。
ダブルピークアレイとシングルピークアレイを区別する方法は?
また、配列が二重ピークを表す場合、2 つのピーク間の最小点を見つける方法は? ピークの外側の最小点 (左側のピークの左側と右側のピークの右側) は、最小点を見つける際に考慮されるべきではありません。
信号のノイズの程度に応じて機能するアルゴリズムの 1 つを次に示します。ここでは、特定のしきい値よりも大きい接続されたポイントのセットとしてピークを定義します。
元のデータが配列Aにあると仮定します。まず、しきい値を見つけます。
t = (max(A)+min(A))/2;
次に、このしきい値tより大きいすべてのポイントを見つけます。
P = A>t;
bwlabelを使用してtより大きい接続されたエントリ ポイントの数をカウントします
L = bwlabel(P);
numberOfPeaks = max(L);
numberOfPeaksは、データ内にいくつのピーク (しきい値よりも大きい接続点) があるかを示します。
2 つのピーク間の最小点を見つけるには、ラベル行列Lを使用して 2 つのピークを分離する点を特定する必要があります。
firstPoint = find(L==1,1,'last')+1;
lastPoint = find(L==2,1,'first')-1;
したがって、最初の 2 つのピーク間の谷は、firsPointとlastPointの間のインデックスを持つポイントです。最小値は次のようになります
minValue = min(A(firstPoint:lastPoint));
Image Processing Toolbox に依存しないソリューション
@Nzbuu が指摘しているように、どちらも画像処理ツールボックス関数 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
PEAKDET関数はループ ベースですが、非常に信頼性が高く高速であることがわかりました。ノイズの多いデータを事前に平滑化する必要はありませんが、パラメータ より大きい差を持つ局所的な最大極値と最小極値を検出しますdelta
。
PEAKDET は左から右に実行されるため、右サイトのピークを見逃すことがあります。それを避けるために、私はそれを2回実行することを好みます:
%# 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
次のように、ローカルの最小/最大を見つけることができます。
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')
その結果:
基本的に、y 値間のデルタが符号を変更する場所を見つけています。データにノイズが多い場合、ローカルの最小値/最大値が多数発生するため、データをフィルタリングする必要がある場合があります。
2 つのピーク間の最小値を見つけるには、次のようにします。
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