对numpy数组重新采样

2024-05-14 00:00:54 发布

您现在位置:Python中文网/ 问答频道 /正文

像这样重新采样数组很容易

 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数组重采样?

应用示例:音频信号重采样/重采样


Tags: numpy示例信号isnot整数数组音频
3条回答

NumPy有^{}进行线性插值:

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有^{}可以进行线性和最近的插值(尽管哪个点最近可能不明显):

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.])

由于scipy.signal.resample可以是very slow,我搜索了其他适合音频的算法。

看起来,Erik de Castro Lopo的SRC(又称秘密兔子代码,又称libsamplerate)是可用的最佳重采样算法之一。

  • 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)使用^{}(“一维线性插值”)重新采样:

既然您提到这是来自audio.WAV文件的数据,那么您可以查看scipy.signal.resample

Resample x to num samples using Fourier method along the given axis.

The resampled signal starts at the same value as x but is sampled with a spacing of len(x) / num * (spacing of x). Because a Fourier method is used, the signal is assumed to be periodic.

你的线性数组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)

相关问题 更多 >