タイムスタンプと値を使用して読み取り値を報告するセンサーがあります。ただし、固定レートで読み取り値を生成しません。
変動レートのデータを扱うのは難しいと思います。ほとんどのフィルターは、固定サンプルレートを想定しています。サンプルレートが固定されているため、グラフの描画も簡単です。
可変サンプルレートから固定サンプルレートにリサンプリングするアルゴリズムはありますか?
タイムスタンプと値を使用して読み取り値を報告するセンサーがあります。ただし、固定レートで読み取り値を生成しません。
変動レートのデータを扱うのは難しいと思います。ほとんどのフィルターは、固定サンプルレートを想定しています。サンプルレートが固定されているため、グラフの描画も簡単です。
可変サンプルレートから固定サンプルレートにリサンプリングするアルゴリズムはありますか?
回答:
最も簡単なアプローチは、Jim Clayが提案するような(線形またはその他の)スプライン補間を行うことです。ただし、バッチ処理の豪華さがあり、特に不均一なサンプルが過剰に決定されている場合は、非常にエレガントな「完全な再構成」アルゴリズムがあります。数値的な理由から、すべての場合に実用的ではないかもしれませんが、少なくとも概念的に知っておく価値はあります。私は最初にこの論文でそれについて読んだ。
トリックは、sinc補間によって均一なサンプルから既に再構築された非均一なサンプルのセットを考慮することです。論文の表記に従って:
これにより、各不均一サンプルに1組の線形方程式が提供されることに注意してください。未知数は等間隔のサンプルです。y (k T )
上記の方程式で、は未知の均一なサンプルの数、は均一なサンプルレートの逆数、は不均一なサンプルの数(よりも大きい場合があります)です。そのシステムの最小二乗解を計算することにより、均一なサンプルを再構築できます。技術的には、不均一なサンプルのみが必要ですが、それらが時間内にどのように「散乱」するかに応じて、補間行列はひどく悪条件になる可能性があります。その場合、通常、より不均一なサンプルを使用すると役立ちます。T m n n
おもちゃの例として、上記の方法と緩やかにジッターされたグリッドでの3次スプライン補間の比較(numpyを使用)を示します。
(上記のプロットを再現するコードは、この回答の最後に含まれています)
言われていることはすべて、高品質で堅牢な方法の場合、次の論文のいずれかから始めるのがおそらくより適切でしょう。
A. Aldroubi and 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()
これは、非同期のサンプルレート変換の問題のように聞こえます。あるサンプルレートから別のサンプルレートに変換するには、sinc補間を実行して信号の連続時間表現を計算し、新しいサンプルレートでリサンプリングします。あなたがしていることは大した違いはありません。サンプル時間を固定するには、信号をリサンプリングする必要があります。
連続時間信号は、各サンプルをsinc関数で畳み込むことにより計算できます。sinc関数は無限に続くため、実用的な有限長のウィンドウ化されたsincのような、より実用的なものを使用します。扱いにくい部分は、サンプルが時間内に移動するため、リサンプリング時に各サンプルに異なる位相オフセットを持つsincを使用する必要がある場合があることです。
サンプリングされた信号からの連続時間信号:
どこあなたのサンプル時間です。ただし、あなたの場合、サンプル時間は固定されていません。したがって、そのサンプルのサンプル時間に置き換える必要があると思います。
これから、信号をリサンプリングできます。
)
ここで、は目的のサンプル時間です。
すべてをまとめると、次のようになります。
これは因果関係も扱いやすいものでもないため、sinc関数は有限サポートの関数に置き換えられ、それに応じて合計の制限が調整されます。
kernel(t)をウィンドウ化されたsincまたは長さ2kの他の同様の関数とします:
これが役立つことを願っていますが、途中でミスをした可能性があり、少し数学を集中させるかもしれません。詳細については、サンプルレートの変換を調査することをお勧めします。ここの他の誰かがより良い説明や解決策を提供できるかもしれません。
ジェイコブの答えは非常に有効だと思います。
歪みを導入するという点でおそらくあまり良くないより簡単な方法は、多項式補間を行うことです。任意の時間サンプルから任意の時間にサンプルを生成するために、線形補間(簡単、良い信号パフォーマンスではない)またはキュービックスプライン(それほど難しくない、優れた信号パフォーマンス)を使用します。
4つまたは6つまたは8つの近隣との線形補間は、データに対して十分に機能する可能性があります。
sincのようなスプラインに飛び込む前に、あなたが完全に理解している方法から始めることをお勧めします...
(もちろん、NO単一の補間方法は、可能性の組み合わせの無数合うことができない
。実際に起こる[ノイズ信号は、エラーメトリック、テスト機能を】
テスト機能よりも、世界のその他の方法は、より多くのノブである。
それにもかかわらずギャラリーメソッドとテスト関数の組み合わせが役立つかもしれません。)
matlabで作業する場合は、timeseriesで作業することで実行できます。
time % is your starting vector of time
data % vector of data you want to resample
data_TS = timeseries(data,time); % define the data as a timeseries
new_time = time(0):dt:time(end); % new vector of time with fixed dt=1/fs
data_res = resample(data_TS,new_time); % data resampled at constant fs
エキゾチックな処理を行う前に、このような単純なものを試すことができます(擬似コード-補間なし、しかし追加可能)
TimeStamp[] //Array of Sensor TimeStamps -NULL terminated – TimeStamp[i] corresponds to Reading[i]
Reading[] //Array of Sensor Readings -NULL terminated
AlgorithmOut //Delimited file of of readings in fixed sample time (5ms)
CurrentSavedReading = Reading[0]
SampleTime=TimeStamp[0] //ms virtual sample time, 5ms fixed samples
i = 0 // loop index
While(TimeStamp[i] != NULL)
{
FileWrite (CurrentSavedReading, AlgorithmOut)//write value to file
SampleTime = SampleTime + 5//ms
if(SampleTime > TimeStamp[i])
{
i++
CurrentSavedReading = Reading[i]
}
}
私見Datageistの答えは正しいですが、ジェイコブの答えは正しくありません。これを確認する簡単な方法は、datageistの推奨アルゴリズムが元のサンプルを補間することを保証していることです(無限の数値精度を想定しています)が、ジェイコブの答えはそうではありません。