Самый простой подход - это выполнить некоторую сплайн-интерполяцию, как предлагает Джим Клэй (линейный или другой). Однако, если у вас есть возможность пакетной обработки, и особенно если у вас есть переопределенный набор неоднородных выборок, есть алгоритм «идеальной реконструкции», который чрезвычайно элегантен. По численным причинам это может быть не практичным во всех случаях, но, по крайней мере, стоит знать об этом концептуально. Я впервые прочитал об этом в этой статье .
Хитрость заключается в том, чтобы рассматривать ваш набор неоднородных выборок как уже восстановленный из однородных выборок путем синхрополяции . Следуя обозначениям в статье:
y(t)=∑k=1Ny(kT)sin(π(t−kT)/T)π(t−kT)/T=∑k=1Ny(kT)sinc(t−kTT).
Обратите внимание, что это обеспечивает набор линейных уравнений, по одному для каждой неоднородной выборки , где неизвестными являются одинаково расположенные выборки y ( k T ) , например:y(t)y(kT)
⎡⎣⎢⎢⎢⎢Y( т0)Y( т1)⋯Y( тм)⎤⎦⎥⎥⎥⎥= ⎡⎣⎢⎢⎢⎢⎢⎢с я н с ( т0- ТT)с я н с ( т1- ТT)⋯с я н с ( тм- ТT)с я н с ( т0- 2 тT)с я н с ( т1- 2 тT)⋯с я н с ( тм- 2 тT)⋯⋯⋯⋯с я н с ( т0- п тT)с я н с ( т1- п тT)⋯с я н с ( тм- п тT)⎤⎦⎥⎥⎥⎥⎥⎥⎡⎣⎢⎢⎢⎢Y( Т)Y( 2 Т)⋯Y( п т)⎤⎦⎥⎥⎥⎥,
В приведенном выше уравнении - это число неизвестных однородных выборок, T - это обратная величина равномерной частоты дискретизации, а m - количество неоднородных выборок (которое может быть больше, чем n ). Вычисляя решение наименьших квадратов этой системы, можно восстановить однородные выборки. Технически, необходимы только n неоднородных выборок, но в зависимости от того, насколько они «разбросаны» во времени, интерполяционная матрица может быть ужасно плохо обусловлена . В этом случае обычно помогает использование большего количества неоднородных образцов.NTмNN
В качестве игрушечного примера, вот сравнение (с использованием numpy ) вышеупомянутого метода и интерполяции кубического сплайна на сетке с мягким волнением:
(Код для воспроизведения приведенного выше сюжета приведен в конце этого ответа)
Все это, как говорится, для качественных и надежных методов, начиная с чего-то в одной из следующих статей, вероятно, будет более уместным
A. Aldroubi и Karlheinz Grochenig, Неоднородный отбор и реконструкция в инвариантных к сдвигу пространствах , SIAM Rev., 2001, no. 4, 585-620. ( pdf ссылка ).
K. Grochenig и H. Schwab, Методы быстрой локальной реконструкции для неоднородной выборки в пространствах , инвариантных к сдвигу , SIAM J. Matrix Anal. Appl., 24 (2003), 899-913.
-
import numpy as np
import pylab as py
import scipy.interpolate as spi
import numpy.random as npr
import numpy.linalg as npl
npr.seed(0)
class Signal(object):
def __init__(self, x, y):
self.x = x
self.y = y
def plot(self, title):
self._plot(title)
py.plot(self.x, self.y ,'bo-')
py.ylim([-1.8,1.8])
py.plot(hires.x,hires.y, 'k-', alpha=.5)
def _plot(self, title):
py.grid()
py.title(title)
py.xlim([0.0,1.0])
def sinc_resample(self, xnew):
m,n = (len(self.x), len(xnew))
T = 1./n
A = np.zeros((m,n))
for i in range(0,m):
A[i,:] = np.sinc((self.x[i] - xnew)/T)
return Signal(xnew, npl.lstsq(A,self.y)[0])
def spline_resample(self, xnew):
s = spi.splrep(self.x, self.y)
return Signal(xnew, spi.splev(xnew, s))
class Error(Signal):
def __init__(self, a, b):
self.x = a.x
self.y = np.abs(a.y - b.y)
def plot(self, title):
self._plot(title)
py.plot(self.x, self.y, 'bo-')
py.ylim([0.0,.5])
def grid(n): return np.linspace(0.0,1.0,n)
def sample(f, x): return Signal(x, f(x))
def random_offsets(n, amt=.5):
return (amt/n) * (npr.random(n) - .5)
def jittered_grid(n, amt=.5):
return np.sort(grid(n) + random_offsets(n,amt))
def f(x):
t = np.pi * 2.0 * x
return np.sin(t) + .5 * np.sin(14.0*t)
n = 30
m = n + 1
# Signals
even = sample(f, np.r_[1:n+1] / float(n))
uneven = sample(f, jittered_grid(m))
hires = sample(f, grid(10*n))
sinc = uneven.sinc_resample(even.x)
spline = uneven.spline_resample(even.x)
sinc_err = Error(sinc, even)
spline_err = Error(spline, even)
# Plot Labels
sn = lambda x,n: "%sly Sampled (%s points)" % (x,n)
r = lambda x: "%s Reconstruction" % x
re = lambda x: "%s Error" % r(x)
plots = [
[even, sn("Even", n)],
[uneven, sn("Uneven", m)],
[sinc, r("Sinc")],
[sinc_err, re("Sinc")],
[spline, r("Cubic Spline")],
[spline_err, re("Cubic Spline")]
]
for i in range(0,len(plots)):
py.subplot(3, 2, i+1)
p = plots[i]
p[0].plot(p[1])
py.show()