重新采样一个numpy数组

问题描述 投票:9回答:5

很容易重新采样数组

 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数组?

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

python arrays numpy audio resampling
5个回答
17
投票

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

10
投票

既然你提到这是来自音频.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)

5
投票

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

似乎Erik de Castro Lopo的SRC(a.k.a.Secret Rabbit Code a.k.a. libsamplerate)是最好的重采样算法之一。

  • 它被scikit的scikit.samplerate使用,但是这个库似乎很难安装(我放弃了Windows)。
  • 幸运的是,有一个易于使用且易于安装的libsamplerate Python包装器,由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重新采样(“一维线性插值”):


4
投票

如果你想要整数采样

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]

0
投票

在信号处理中,您可以将重新采样视为基本上重新调整数组,并使用最近,线性,立方等方法使用非整数索引插入缺失值或值。

使用scipy.interpolate.interp1d,您可以使用以下函数实现一维重采样

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

e.f.:

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.])
© www.soinside.com 2019 - 2024. All rights reserved.