L'approche la plus simple consiste à effectuer une sorte d'interpolation spline comme le suggère Jim Clay (linéaire ou autre). Cependant, si vous avez le luxe du traitement par lots, et surtout si vous avez un ensemble surdéterminé d'échantillons non uniformes, il existe un algorithme de "reconstruction parfaite" qui est extrêmement élégant. Pour des raisons numériques, cela peut ne pas être pratique dans tous les cas, mais cela vaut au moins la peine d'être connu conceptuellement. J'ai d'abord lu à ce sujet dans cet article .
L'astuce consiste à considérer votre ensemble d'échantillons non uniformes comme ayant déjà été reconstruit à partir d'échantillons uniformes par interpolation sinc . En suivant la notation dans le papier:
y(t)=∑k=1Ny(kT)sin(π(t−kT)/T)π(t−kT)/T=∑k=1Ny(kT)sinc(t−kTT).
Notez que cela fournit un ensemble d'équations linéaires, une pour chaque échantillon non uniforme , où les inconnues sont les échantillons équidistants , comme ceci: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)⎤⎦⎥⎥⎥⎥.
Dans l'équation ci-dessus, est le nombre d'échantillons uniformes inconnus, est l'inverse de la fréquence d'échantillonnage uniforme et est le nombre d'échantillons non uniformes (qui peut être supérieur à ). En calculant la solution des moindres carrés de ce système, les échantillons uniformes peuvent être reconstruits. Techniquement, seuls échantillons non uniformes sont nécessaires, mais en fonction de leur «diffusion» dans le temps, la matrice d'interpolation peut être horriblement mal conditionnée . Lorsque c'est le cas, l'utilisation d'un plus grand nombre d'échantillons non uniformes est généralement utile.T m n nnTmnn
À titre d'exemple de jouet, voici une comparaison (en utilisant numpy ) entre la méthode ci-dessus et l'interpolation de spline cubique sur une grille légèrement instable:
(Le code pour reproduire le graphique ci-dessus est inclus à la fin de cette réponse)
Tout cela étant dit, pour des méthodes robustes de haute qualité, commencer par quelque chose dans l'un des articles suivants serait probablement plus approprié:
A. Aldroubi et Karlheinz Grochenig, Échantillonnage non uniforme et reconstruction dans les espaces invariables par décalage , SIAM Rev., 2001, no. 4, 585-620. ( lien pdf ).
K. Grochenig et H. Schwab, Méthodes de reconstruction locale rapide pour l'échantillonnage non uniforme dans les espaces invariants par décalage , 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()