web-dev-qa-db-ja.com

numpy配列をリサンプルする

次のように配列をリサンプルするのは簡単です

 a = numpy.array([1,2,3,4,5,6,7,8,9,10])

整数リサンプリング係数を使用します。たとえば、係数が2の場合:

b = a[::2]    # [1 3 5 7 9]

しかし、整数以外のリサンプリング係数では、それほど簡単には機能しません。

c = a[::1.5]    # [1 2 3 4 5 6 7 8 9 10]  => not what is needed...

(線形補間を使用):

[1 2.5 4 5.5 7 8.5 10]

または(配列内の最近傍を取得することにより)

[1 3 4 6 7 9 10]

非整数のリサンプリング係数を使用してnumpy配列をリサンプリングする方法?

アプリケーションの例:オーディオ信号のリサンプリング/ピッチング

13
Basj

scipy.signal.resample非常に遅い になる可能性があるため、オーディオ用に適応された他のアルゴリズムを検索しました。

Erik de Castro Lopoの [〜#〜] src [〜#〜] (a.k.a.秘密のウサギのコードa.k.a. libsamplerate)は、利用可能な最高のリサンプリングアルゴリズムの1つであるようです。

  • Scikitのscikit.samplerateで使用されていますが、このライブラリはインストールが複雑なようです(Windowsでは諦めました)。

  • 幸いにも、使いやすく、インストールが簡単なPython libsamplerateのラッパーで、Tino Wagnerによって作成されています: https:// pypi。 org/project/samplerate /pip install samplerateを使用したインストール。使用法:

    import samplerate
    from scipy.io import wavfile
    sr, x = wavfile.read('input.wav')  # 48 khz file
    y = samplerate.resample(x, 44100 * 1.0 / 48000, 'sinc_best')  
    

多くのリサンプリングソリューションの興味深い読書/比較: http://signalsprocessed.blogspot.com/2016/08/audio-resampling-in-python.html


補遺:リサンプリングされた周波数掃引のスペクトログラムの比較(20hzから20khz):

1)オリジナル

2)libsamplerate/samplerateモジュールでリサンプリング

3) numpy.interp ( "1次元線形補間")でリサンプリング:

7
Basj

NumPyには numpy.interp 線形補間を行います:

In [1]: numpy.interp(np.arange(0, len(a), 1.5), np.arange(0, len(a)), a)
Out[1]: array([  1. ,   2.5,   4. ,   5.5,   7. ,   8.5,  10. ])

SciPyには scipy.interpolate.interp1d これは、線形補間と最も近い補間を実行できます(ただし、どの点が最も近いかは明らかでない場合があります)。

In [2]: from scipy.interpolate import interp1d
In [3]: xp = np.arange(0, len(a), 1.5)
In [4]: lin = interp1d(np.arange(len(a)), a)

In [5]: lin(xp)
Out[5]: array([  1. ,   2.5,   4. ,   5.5,   7. ,   8.5,  10. ])

In [6]: nearest = interp1d(np.arange(len(a)), a, kind='nearest')

In [7]: nearest(xp)
Out[7]: array([  1.,   2.,   4.,   5.,   7.,   8.,  10.])
20
xnx

これがオーディオ.WAVファイルからのデータであることを説明したので、_scipy.signal.resample_を見るかもしれません。

指定された軸に沿ってフーリエ法を使用してxからnumサンプルをリサンプルします。

再サンプリングされた信号はxと同じ値で始まりますが、len(x) / num * (spacing of x)の間隔でサンプリングされます。フーリエ法が使用されるため、信号は周期的であると想定されます。

線形配列aは、外観が周期的ではないため、これをテストするのに適していません。ただし、sinデータを検討してください。

_x=np.arange(10)
y=np.sin(x)
y1, x1 =signal.resample(y,15,x)  # 10 pts resampled at 15
_

これらをどちらかと比較してください

_y1-np.sin(x1) # or
plot(x, y, x1, y1)
_
10
hpaulj

そして、整数サンプリングをしたい場合

a = numpy.array([1,2,3,4,5,6,7,8,9,10])
factor = 1.5
x = map(int,numpy.round(numpy.arange(0,len(a),factor)))
sampled = a[x]
4
EngineeredE

信号処理では、リサンプリングは基本的に配列を再スケーリングし、最も近い、線形、3次などの方法を使用して、欠損値または非整数インデックスの値を補間することと考えることができます。

scipy.interpolate.interp1d 、次の関数を使用して1次元のリサンプリングを実現できます

def resample(x, factor, kind='linear'):
    n = np.ceil(x.size / factor)
    f = interp1d(np.linspace(0, 1, x.size), x, kind)
    return f(np.linspace(0, 1, n))

例えば。:

a = np.array([1,2,3,4,5,6,7,8,9,10])
resample(a, factor=1.5, kind='linear')

収量

array([ 1. ,  2.5,  4. ,  5.5,  7. ,  8.5, 10. ])

そして

a = np.array([1,2,3,4,5,6,7,8,9,10])
resample(a, factor=1.5, kind='nearest')

収量

array([ 1.,  2.,  4.,  5.,  7.,  8., 10.])
1
yellow01