35

非常に長いシーケンスがあると想像してください。シーケンスがすべてゼロである間隔を見つける最も効率的な方法は何ですか (より正確には、シーケンスがゼロに近い値に低下しますabs(X)<eps):

簡単にするために、次のシーケンスを想定します。

sig = [1 1 0 0 0 0 1 1 1 1 1 0 1 0 0 0 1 1 1 1 1 1 1 1 0 0 1 1 1 0];

次の情報を取得しようとしています。

startIndex   EndIndex    Duration
3            6           4
12           12          1
14           16          3
25           26          2
30           30          1

次に、この情報を使用して、duration >= から指定された値 (たとえば3) の間隔を見つけ、これらすべての間隔の値のインデックスを組み合わせて返します。

indices = [3 4 5 6 14 15 16];

その最後の部分は、前の質問に関連しています。

MATLAB: 開始/終了インデックスのリストからのベクトル化された配列の作成

これは私がこれまでに持っているものです:

sig = [1 1 0 0 0 0 1 1 1 1 1 0 1 0 0 0 1 1 1 1 1 1 1 1 0 0 1 1 1 0];
len = length(sig);
thresh = 3;

%# align the signal with itself successively shifted by one
%# v will thus contain 1 in the starting locations of the zero interval
v = true(1,len-thresh+1);
for i=1:thresh
    v = v & ( sig(i:len-thresh+i) == 0 );
end

%# extend the 1's till the end of the intervals
for i=1:thresh-1
    v(find(v)+1) = true;
end

%# get the final indices
v = find(v);

コードのベクトル化/最適化を検討していますが、他のソリューションも受け入れています。多数の長い生体信号を処理しているため、空間と時間の効率が非常に重要であることを強調しなければなりません。

4

6 に答える 6

33

これらは、与えられたベクトルから始めて、ベクトル化された方法で問題を解決するために私が取るステップですsig

  • まず、ベクトルにしきい値を設定して、ゼロと1のベクトルを取得しtsigます(信号の絶対値がゼロに十分に近づくゼロ、他の場所にあるゼロ)。

    tsig = (abs(sig) >= eps);  %# Using eps as the threshold
    
  • 次に、関数DIFFおよびFINDを使用して、ゼロの各文字列の開始インデックス、終了インデックス、および期間を見つけます。

    dsig = diff([1 tsig 1]);
    startIndex = find(dsig < 0);
    endIndex = find(dsig > 0)-1;
    duration = endIndex-startIndex+1;
    
  • 次に、ある値(例では3など)以上の期間を持つゼロの文字列を見つけます。

    stringIndex = (duration >= 3);
    startIndex = startIndex(stringIndex);
    endIndex = endIndex(stringIndex);
    
  • 最後に、リンクされた質問に対する私の回答の方法を使用して、最終的なインデックスのセットを生成します。

    indices = zeros(1,max(endIndex)+1);
    indices(startIndex) = 1;
    indices(endIndex+1) = indices(endIndex+1)-1;
    indices = find(cumsum(indices));
    
于 2010-07-18T05:14:30.877 に答える
10

長さがゼロの文字列を見つけることにより、文字列検索タスクとしてこれを解決できますthresh(STRFIND関数は非常に高速です)

startIndex = strfind(sig, zeros(1,thresh));

長い部分文字列は複数の場所でマークされますが、間隔の開始startIndexから終了までの間に場所を追加すると、最終的には結合されることに注意してくださいstart+thresh-1

indices = unique( bsxfun(@plus, startIndex', 0:thresh-1) )';

この最後のステップは、リンクされた質問の@gnoviceによるCUMSUM/FINDソリューションといつでも交換できることに注意してください。

于 2010-07-18T19:34:00.163 に答える
1
function indice=sigvec(sig,thresh)
    %extend sig head and tail to avoid 0 head and 0 tail

    exsig=[1,sig,1];
    %convolution sig with extend sig
    cvexsig=conv(exsig,ones(1,thresh));
    tempsig=double(cvexsig==0);

    indice=find(conv(tempsig,ones(1,thresh)))-thresh;
于 2010-07-18T02:31:18.157 に答える
1

genovice による上記の回答を変更して、ベクトル内の非ゼロ要素のインデックスを次のように見つけることができます。

    tsig = (abs(sig) >= eps);
    dsig = diff([0 tsig 0]);
    startIndex = find(dsig > 0);
    endIndex = find(dsig < 0)-1;
    duration = endIndex-startIndex+1;
于 2016-11-28T08:56:39.400 に答える
0

それを行う最も MATLAB/「​​ベクトル化された」方法は、[-1 1] のようなフィルターを使用して信号の畳み込みを計算することだと思います。関数 conv のドキュメントを参照してください。次に、conv の出力で find を使用して、関連するインデックスを取得します。

于 2010-07-18T02:13:58.993 に答える
0

gnovice が示したように、「ほぼゼロ」を本当にゼロにするしきい値テストを行います。

logcl = abs(sig(:)) >= zero_tolerance;

次に、累積合計が増加していない領域を見つけます。

cs = cumsum(logcl);
islands = cs(1+thresh:end) == cs(1:end-thresh);

インデックスの範囲を埋めるための gnovice の優れた方法を思い出す

v = zeros(1,max(endInd)+1);   %# An array of zeroes
v(startInd) = 1;              %# Place 1 at the starts of the intervals
v(endInd+1) = v(endInd+1)-1;  %# Add -1 one index after the ends of the intervals
indices = find(cumsum(v));  %# Perform a cumulative sum and find the nonzero entries

islands私たちのベクトルはすでに場所にあることに注意してください.startInd私たちの目的のために、endInd常にthreshスポットが後で来ることに注意してislandsください.

endcap = zeros(thresh,1);
indices = find(cumsum([islands ; endcap] - [endcap ; islands]))

テスト

sig = [1 1 0 0 0 0 1 1 1 1 1 0 1 0 0 0 1 1 1 1 1 1 1 1 0 0 1 1 1 0];
logcl = abs(sig(:)) >= .1;
cs = cumsum(logcl);
islands = cs(1+thresh:end) == cs(1:end-thresh);
endcap = zeros(thresh,1);
indices = find(cumsum([islands ; endcap] - [endcap ; islands]))
indices =

     2
     3
     4
     5
    13
    14
    15
于 2014-11-04T01:37:10.147 に答える