12

でこぼこで、信号が特定のしきい値を下回って(以前は)、特定の他のしきい値を超えたポイントを検出したいと思います。これは、ノイズの存在下でのデバウンスや正確なゼロクロッシングなどのためのものです。

このような:

import numpy

# set up little test problem
N = 1000
values = numpy.sin(numpy.linspace(0, 20, N))
values += 0.4 * numpy.random.random(N) - 0.2
v_high = 0.3
v_low = -0.3

# find transitions from below v_low to above v_high    
transitions = numpy.zeros_like(values, dtype=numpy.bool)

state = "high"

for i in range(N):
    if values[i] > v_high:
        # previous state was low, this is a low-to-high transition
        if state == "low":
            transitions[i] = True
        state = "high"
    if values[i] < v_low:
        state = "low"

配列を明示的にループせずにこれを行う方法が欲しいのですが、各状態値は前の状態に依存するため、方法は考えられません。ループなしで行うことは可能ですか?

4

2 に答える 2

16

これは次のように実行できます。

def hyst(x, th_lo, th_hi, initial = False):
    hi = x >= th_hi
    lo_or_hi = (x <= th_lo) | hi
    ind = np.nonzero(lo_or_hi)[0]
    if not ind.size: # prevent index error if ind is empty
        return np.zeros_like(x, dtype=bool) | initial
    cnt = np.cumsum(lo_or_hi) # from 0 to len(x)
    return np.where(cnt, hi[ind[cnt-1]], initial)

説明:indは、信号が下限しきい値を下回っている、または上限しきい値を上回っているすべてのサンプルのインデックスであり、「スイッチ」の位置が明確に定義されています。ではcumsum、最後の明確に定義されたサンプルのインデックスを指すある種のカウンターを作成します。入力ベクトルの開始点が 2 つのしきい値の間にある場合はcnt0 になるため、関数を使用して対応する出力を初期値に設定する必要がありwhereます。

クレジット: これは、Matlab フォーラムの古い投稿で見つけたトリックで、Numpy に翻訳しました。このコードは少し理解しにくく、さまざまな中間配列を割り当てる必要もあります。Numpy に、単純な for ループに似た専用の関数が含まれているが、速度のために C で実装されているとよいでしょう。

クイックテスト:

x = np.linspace(0,20, 1000)
y = np.sin(x)
h1 = hyst(y, -0.5, 0.5)
h2 = hyst(y, -0.5, 0.5, True)
plt.plot(x, y, x, -0.5 + h1, x, -0.5 + h2)
plt.legend(('input', 'output, start=0', 'output, start=1'))
plt.title('Thresholding with hysteresis')
plt.show()

結果: ここに画像の説明を入力

于 2014-04-25T11:23:08.583 に答える