L'approccio più semplice è fare una sorta di interpolazione della spline come suggerisce Jim Clay (lineare o altro). Tuttavia, se si dispone del lusso dell'elaborazione batch, e soprattutto se si dispone di una serie eccessiva di campioni non uniformi, esiste un algoritmo di "ricostruzione perfetta" estremamente elegante. Per ragioni numeriche, potrebbe non essere pratico in tutti i casi, ma almeno vale la pena conoscerlo concettualmente. L'ho letto per la prima volta in questo documento .
Il trucco è considerare il tuo set di campioni non uniformi come già ricostruito da campioni uniformi attraverso un'interpolazione sincera . Seguendo la notazione nel documento:
y( t ) = ∑k = 1Ny( k T) sin( π( t - k T) / T)π( t - k T) / T= ∑k = 1Ny( k T) s i n c ( t - k TT) .
Si noti che ciò fornisce un insieme di equazioni lineari, una per ciascun campione non uniforme , dove gli incogniti sono i campioni equidistanziati , in questo modo:y ( k T )y( t )y( k T)
⎡⎣⎢⎢⎢⎢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)⎤⎦⎥⎥⎥⎥.
Nell'equazione precedente, è il numero di campioni uniformi sconosciuti, è l'inverso della frequenza di campionamento uniforme e è il numero di campioni non uniformi (che può essere maggiore di ). Calcolando la soluzione dei minimi quadrati di quel sistema, è possibile ricostruire i campioni uniformi. Tecnicamente, sono necessari solo campioni non uniformi, ma a seconda di quanto "dispersi" siano nel tempo, la matrice di interpolazione può essere orribilmente mal condizionata . In questo caso, l'utilizzo di più campioni non uniformi di solito aiuta.T m n nnTmnn
A titolo di esempio di giocattolo, ecco un confronto (usando numpy ) tra il metodo sopra e l'interpolazione della spline cubica su una griglia leggermente jitter:
(Il codice per riprodurre la trama sopra è incluso alla fine di questa risposta)
Detto questo, per metodi robusti e di alta qualità, partire da qualcosa in uno dei seguenti documenti sarebbe probabilmente più appropriato:
A. Aldroubi e Karlheinz Grochenig, Campionamento non uniforme e ricostruzione in spazi invarianti a turni , SIAM Rev., 2001, n. 4, 585-620. ( link pdf ).
K. Grochenig e H. Schwab, Metodi di ricostruzione locale veloce per campionamento non uniforme in spazi invarianti a turni , 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()