A abordagem mais simples é fazer algum tipo de interpolação de splines, como Jim Clay sugere (linear ou não). No entanto, se você tem o luxo do processamento em lote e, especialmente, se você tem um conjunto sobredeterminado de amostras não uniformes, existe um algoritmo de "reconstrução perfeita" extremamente elegante. Por razões numéricas, pode não ser prático em todos os casos, mas vale a pena conhecer conceitualmente. Eu li pela primeira vez sobre isso neste artigo .
O truque é considerar o seu conjunto de amostras não uniformes como já tendo sido reconstruído a partir de amostras uniformes por meio de interpolação sincera . Após a notação no artigo:
y(t)=∑k=1Ny(kT)sin(π(t−kT)/T)π(t−kT)/T=∑k=1Ny(kT)sinc(t−kTT).
Observe que isso fornece um conjunto de equações lineares, uma para cada amostra não uniforme , onde as incógnitas são as amostras igualmente espaçadas , da seguinte forma:y ( k T )y(t)y(kT)
⎡⎣⎢⎢⎢⎢y(t0)y(t1)⋯y(tm)⎤⎦⎥⎥⎥⎥=⎡⎣⎢⎢⎢⎢⎢⎢sinc(t0−TT)sinc(t1−TT)⋯sinc(tm−TT)sinc(t0−2TT)sinc(t1−2TT)⋯sinc(tm−2TT)⋯⋯⋯⋯sinc(t0−nTT)sinc(t1−nTT)⋯sinc(tm−nTT)⎤⎦⎥⎥⎥⎥⎥⎥⎡⎣⎢⎢⎢⎢y(T)y(2T)⋯y(nT)⎤⎦⎥⎥⎥⎥.
Na equação acima, é o número de amostras uniformes desconhecidas, é o inverso da taxa de amostragem uniforme, e é o número de amostras não uniformes (que podem ser maiores que ). Calculando a solução de mínimos quadrados desse sistema, as amostras uniformes podem ser reconstruídas. Tecnicamente, apenas amostras não uniformes são necessárias, mas dependendo de quão "dispersas" elas estão no tempo, a matriz de interpolação pode estar terrivelmente mal condicionada . Nesse caso, o uso de mais amostras não uniformes geralmente ajuda.T m n nnTmnn
Como um exemplo de brinquedo, veja uma comparação (usando numpy ) entre o método acima e a interpolação de spline cúbico em uma grade levemente instável:
(O código para reproduzir o gráfico acima está incluído no final desta resposta)
Tudo o que foi dito, para métodos robustos de alta qualidade, começando com algo em um dos seguintes documentos provavelmente seria mais apropriado:
A. Aldroubi e Karlheinz Grochenig, Amostragem não uniforme e reconstrução em espaços invariantes a turnos , SIAM Rev., 2001, no. 4, 585-620. ( link em pdf ).
K. Grochenig e H. Schwab, Métodos rápidos de reconstrução local para amostragem não uniforme em espaços invariantes por turnos , 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()