繁体   English   中英

重采样,插值矩阵

[英]resampling, interpolating matrix

我正在尝试为绘图目的插入一些数据。 例如,给定N个数据点,我希望能够生成“平滑”图,由10 * N左右的内插数据点组成。

我的方法是生成N×10 * N矩阵并计算原始向量和我生成的矩阵的内积,得到1乘10 * N向量。 我已经计算出我想用于插值的数学运算,但我的代码非常慢。 我对Python很陌生,所以我希望这里的一些专家可以给我一些关于如何加速我的代码的想法。

我认为问题的一部分是生成矩阵需要10 * N ^ 2次调用以下函数:

def sinc(x):
    import math
    try:
        return math.sin(math.pi * x) / (math.pi * x)
    except ZeroDivisionError:
        return 1.0

(这来自采样理论 。基本上,我试图从其样本中重新生成信号,并将其上采样到更高的频率。)

矩阵由以下生成:

def resampleMatrix(Tso, Tsf, o, f):
    from numpy import array as npar
    retval = []

    for i in range(f):
        retval.append([sinc((Tsf*i - Tso*j)/Tso) for j in range(o)])

    return npar(retval)

我正在考虑将任务分解成更小的部分因为我不喜欢坐在内存中的N ^ 2矩阵的想法。 我可以将'resampleMatrix'变成一个生成器函数并逐行执行内部产品,但我不认为这会加速我的代码,直到我开始在内存中分页内容。

提前感谢您的建议!

这是上采样。 有关示例解决方案,请参阅重新取样/上采样的帮助

快速实现此目的(对于离线数据,如绘图应用程序)是使用FFT。 这就是SciPy的原生resample()函数所做的。 但它假定是一个周期性信号, 所以它并不完全相同 看到这个参考

这是关于时域实信号插值的第二个问题,确实很重要。 只有当原始x(n)序列在其全时间间隔内是周期性时,这种精确的插值算法才能提供正确的结果。

您的函数假定信号的样本在定义的范围之外都是0,因此这两种方法将偏离中心点。 如果先用大量​​的零填充信号,它将产生非常接近的结果。 在这里没有显示的情节边缘还有几个零:

在此输入图像描述

对于重采样目的,立方插值不正确。 这个例子是一个极端情况(接近采样频率),但正如你所看到的,三次插值甚至不是很接近。 对于较低的频率,它应该非常准确。

如果要以非常通用且快速的方式插入数据,样条或多项式非常有用。 Scipy有scipy.interpolate模块,非常有用。 您可以在官方页面中找到许多示例

你的问题并不完全清楚; 你正试图优化你发布的代码,对吧?

像这样重写sinc应该会大大加快速度。 此实现避免检查是否在每次调用时导入数学模块,不执行三次属性访问,并使用条件表达式替换异常处理:

from math import sin, pi
def sinc(x):
    return (sin(pi * x) / (pi * x)) if x != 0 else 1.0

你也可以尝试通过直接创建一个numpy.array(而不是列表列表)来避免创建矩阵两次(并在内存中并行保存两次):

def resampleMatrix(Tso, Tsf, o, f):
    retval = numpy.zeros((f, o))
    for i in xrange(f):
        for j in xrange(o):
            retval[i][j] = sinc((Tsf*i - Tso*j)/Tso)
    return retval

(在Python 3.0及更高版本上用x替换xrange)

最后,您可以使用numpy.arange创建行,也可以在每行甚至整个矩阵上调用numpy.sinc:

def resampleMatrix(Tso, Tsf, o, f):
    retval = numpy.zeros((f, o))
    for i in xrange(f):
        retval[i] = numpy.arange(Tsf*i / Tso, Tsf*i / Tso - o, -1.0)
    return numpy.sinc(retval)

这应该比原始实现快得多。 尝试不同的这些想法的组合,并测试他们的表现,看看哪个最好!

这里是scipy的1d插值的最小例子 - 不像重新发明那么有趣,但是。
情节看起来像sinc ,这不是巧合:尝试google spline resample“近似sinc”。
(可能是更少的本地/更多的点击⇒更好的近似,但我不知道当地的单变量线是如何。)

""" interpolate with scipy.interpolate.UnivariateSpline """
from __future__ import division
import numpy as np
from scipy.interpolate import UnivariateSpline
import pylab as pl

N = 10 
H = 8
x = np.arange(N+1)
xup = np.arange( 0, N, 1/H )
y = np.zeros(N+1);  y[N//2] = 100

interpolator = UnivariateSpline( x, y, k=3, s=0 )  # s=0 interpolates
yup = interpolator( xup )
np.set_printoptions( 1, threshold=100, suppress=True )  # .1f
print "yup:", yup

pl.plot( x, y, "green",  xup, yup, "blue" )
pl.show()

添加了feb 2010:另请参阅基本样条插值 - 几个线条的numpy

我不太确定你要做什么,但是你可以做一些加速来创建矩阵。 Braincore建议使用numpy.sinc是第一步,但第二步是要意识到numpy函数想要在numpy数组上工作,它们可以在C语言中执行循环,并且可以比单个元素更快地完成。

def resampleMatrix(Tso, Tsf, o, f):
    retval = numpy.sinc((Tsi*numpy.arange(i)[:,numpy.newaxis]
                         -Tso*numpy.arange(j)[numpy.newaxis,:])/Tso)
    return retval

诀窍在于,通过使用numpy.newaxis索引aranges,numpy将具有形状i的数组转换为形状为ix 1的数组,将形状为j的数组转换为形状1 x j。 在减法步骤中,numpy将“广播”每个输入以充当aixj形阵列并进行减法。 (“广播”是numpy的术语,反映了没有额外的副本将ix 1拉伸到ix j的事实。)

现在numpy.sinc可以迭代编译代码中的所有元素,比你可以编写的任何for循环快得多。

(如果在减法之前进行除法,则可以进行额外的加速,特别是在后者中,除法取消乘法。)

唯一的缺点是你现在支付额外的Nx10 * N阵列以保持差异。 如果N很大并且内存是个问题,那么这可能是一个破坏者。

否则,您应该能够使用numpy.convolve编写此numpy.convolve 从我刚刚学到的关于sinc-interpolation的一点点开始,我会说你想要像numpy.convolve(orig,numpy.sinc(numpy.arange(j)),mode="same") 但我可能错误的具体细节。

如果您唯一的兴趣是“生成”平滑的“情节”,我将使用简单的多项式样条曲线拟合:

对于任何两个相邻的数据点,可以从这些数据点的坐标和左右两个附加点(忽略边界点)计算三次多项式函数的系数。这将在一条漂亮的平滑曲线上生成点。一个连续的第一个dirivitive。 将4个坐标转换为4个多项式系数有一个直接的公式,但我不想剥夺你查找它的乐趣; o)。

小改进。 使用内置的numpy.sinc(x)函数,该函数在已编译的C代码中运行。

可能的更大改进:你可以动态插值(当绘图发生时)? 或者你是否只接受一个只接受矩阵的绘图库?

我建议您检查算法,因为这是一个非常重要的问题。 具体来说,我建议您访问Hu和Pavlidis(1991)的文章“使用圆锥花键的功能绘图”(IEEE计算机图形和应用程序)。 它们的算法实现允许对函数进行自适应采样,使得渲染时间小于规则间隔的方法。

摘要如下:

提出了一种方法,其中,给定函数的数学描述,产生近似函数图的圆锥样条。 选择圆锥曲线作为原始曲线,因为对于已经包含在一些设备驱动器中的圆锥曲线存在简单的增量绘图算法,并且存在用于圆锥曲线局部近似的简单算法。 根据基于一阶导数的原函数的形状分析,介绍了一种自适应选择节点的分裂合并算法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM