重新采样信号并使用 numpy.interp 从不同的点开始

信息处理 Python 插值 麻木的
2022-02-21 08:15:56

我试图在 Python 中重新采样信号,仅通过给出新的和旧的步骤。直到这里,我的功能都可以正常工作。但是现在我想在除初始信号之外的特定点开始重采样信号,因此它将与我拥有的另一个信号的点相匹配以进行乘法运算。

import matplotlib.pyplot as plt
import numpy as np

# DISCLAIMER: This function is copied from https://github.com/nwhitehead/swmixer/blob/master/swmixer.py, 
#             which was released under LGPL. 
def resample_by_interpolation(sig, output_step, input_step, x_range=[0, None] ):

scale = input_step / output_step
# calculate new length of sample
n = round(len(sig) * scale)

# First value (start from)
if None not in x_range: 
    f_init = round(x_range[0] / output_step + 0.5) * output_step
    start = f_init / x_range[1]
else: start, f_init = (0.0, 0)

# using endpoint=False gets less noise in the resampled sound
resampled_sg = np.interp(
    np.linspace(start, 1.0, n, endpoint=False),  # where to interpret
    np.linspace(0.0, 1.0, len(sig), endpoint=False),  # known positions
    sig,  # known data points
)
return resampled_sg, f_init

我添加了这个x_rangestart条件来定位初始点。找到了点,但插值被弄乱了,有一些位移。这是正弦曲线的示例:

x = np.linspace(2, 8*np.pi, 50)
y = np.sin(x)
output_step, input_step = ((x[1]-x[0])/2, x[1]-x[0])
new_y, f_init = resample_by_interpolation(y, output_step, input_step, x_range= [2.5, 25])
new_x = np.linspace(f_init, 25, len(new_y), endpoint=False)


plt.plot(x, y, '--')
plt.plot(new_x, new_y, '-x')
plt.show()

重采样不应取代信号。我可能会在这里错过什么?

正弦重采样示例

编辑: 根据@Peter K. 的建议,我对代码做了一些小改动,以准确地从所需的点开始:

x = np.linspace(2, 25, 50)
y = np.sin(x)
output_step, input_step = ((x[1]-x[0])/2, x[1]-x[0])
new_y = resample_by_interpolation(y, output_step, input_step, x_range= [2.5, 25])
new_x = np.linspace(min(x), max(x), len(new_y))

x_start = 2.5
new_new_x = next(xxx for xxx, val in enumerate(new_x) if val > x_start)

# Find the exactly start point
x1 = [new_x[new_new_x-1], new_x[new_new_x]]
y1 = [new_y[new_new_x-1], new_y[new_new_x]]
y_new = np.interp(x_start, x1, y1)

new_y = resample_by_interpolation([y_new, *new_y[new_new_x:]], output_step, output_step)
new_x = np.linspace(x_start, max(x), len(new_y))

plt.plot(x,y,'--')
plt.plot(new_x, new_y)

plt.show()

虽然它没有遵循确切的时间步长。更糟糕的是endpoint=Falsein linspace

1个回答

好的,这是另一个尝试。

def resample_by_interpolation_with_offset(sig, output_step, input_step, x_start, x_end, x_new_start):
    scale = input_step / output_step
    # calculate new length of sample
    n = round(len(sig) * scale - (x_new_start-x_start)/output_step)
    new_x = np.linspace(x_new_start, x_end, n)

    new_y = np.interp(
        new_x,  # where to interpret
        np.linspace(x_start, x_end, len(sig)),  # known positions
        sig,  # known data points
    )
    return new_x, new_y

x = np.linspace(2, 8*np.pi, 50)
y = np.sin(x)
output_step, input_step = ((x[1]-x[0])/2, x[1]-x[0])
new_x, new_y = resample_by_interpolation_with_offset(y, output_step, input_step, min(x), max(x), 10)

plt.plot(x, y, 'o')
plt.plot(new_x, new_y, 'x')
plt.show()

这产生了以下情节。

第三次尝试...

这似乎得到exactly points and time step了你的要求。


我不确定您复制的代码要做什么,但这不是您想要的。

下面更新的代码输出了两个图表:

这是原始图(更改了线条样式,因此我们可以更好地看到两者)。

原来的

轴而不是原始的比例绘制的,因此可以看出点数是原来的两倍。xx

表明我们有双倍的点数

要从特定的值(例如)开始,只需执行以下操作:xx_start

x_start = 2.5
new_new_x = next(xxx for xxx, val in enumerate(new_x) if val > x_start)
plt.plot(x,y,'--')
plt.plot(new_x[new_new_x:], new_y[new_new_x:])

完成完整插值后。这会产生一些似乎是你所追求的东西。

从其他地方开始的插值图。


下面的原始代码

def resample_by_interpolation(sig, output_step, input_step, x_range=[0, None] ):

    scale = input_step / output_step
    # calculate new length of sample
    n = round(len(sig) * scale)

    resampled_sg = np.interp(
        np.linspace(0, 1.0, n),  # where to interpret
        np.linspace(0.0, 1.0, len(sig)),  # known positions
        sig,  # known data points
    )
    return resampled_sg


x = np.linspace(2, 8*np.pi, 50)
y = np.sin(x)
output_step, input_step = ((x[1]-x[0])/2, x[1]-x[0])
new_y = resample_by_interpolation(y, output_step, input_step, x_range= [2.5, 25])
new_x = np.linspace(min(x), max(x), len(new_y))


plt.figure(1)
plt.plot(x, y, '--')
plt.plot(new_x, new_y, 'x')
plt.show()

plt.figure(2)
plt.plot(y)
plt.plot(new_y)