可変レートから固定レートに再サンプリングするアルゴリズムとは何ですか?


27

タイムスタンプと値を使用して読み取り値を報告するセンサーがあります。ただし、固定レートで読み取り値を生成しません。

変動レートのデータを扱うのは難しいと思います。ほとんどのフィルターは、固定サンプルレートを想定しています。サンプルレートが固定されているため、グラフの描画も簡単です。

可変サンプルレートから固定サンプルレートにリサンプリングするアルゴリズムはありますか?


これはプログラマーからのクロスポストです。これは尋ねるのに良い場所だと言われました。Programmers.stackexchange.com/questions/193795/…–
FigBug

センサーが測定値を報告するタイミングを決定するものは何ですか?測定値が変更されたときにのみ測定値を送信しますか?簡単なアプローチは、生成された読み取り値間の最短時間よりも短い「仮想サンプル間隔」(T)を選択することです。アルゴリズム入力では、最後に報告された読み取り値(CurrentReading)のみを保存します。アルゴリズム出力で、CurrentReadingをT秒ごとに「新しいサンプル」として報告します。これにより、フィルターまたはグラフサービスは一定の速度(T秒ごと)で読み取り値を受け取ります。ただし、これがあなたのケースで適切かどうかはわかりません。
user2718

5msまたは10msごとにサンプリングしようとします。ただし、優先度の低いタスクなので、見逃したり遅れたりする可能性があります。タイミングは1ミリ秒まで正確です。処理はリアルタイムではなくPC上で行われるため、実装が簡単であれば遅いアルゴリズムでも問題ありません。
FigBug

1
フーリエ再構成を見たことがありますか?不均一にサンプリングされたデータに基づくフーリエ変換があります。通常の方法は、フーリエ画像を均等にサンプリングされた時間領域に戻すことです。
mbaitoff

3
サンプリングしている基になる信号の特性を知っていますか?不規則な間隔のデータが、測定される信号の帯域幅に比べてまだかなり高いサンプルレートである場合、等間隔のタイムグリッドへの多項式補間のような単純なものがうまく機能する可能性があります。
ジェイソンR

回答:


21

最も簡単なアプローチは、Jim Clayが提案するような(線形またはその他の)スプライン補間を行うことです。ただし、バッチ処理の豪華さがあり、特に不均一なサンプルが過剰に決定されている場合は、非常にエレガントな「完全な再構成」アルゴリズムがあります。数値的な理由から、すべての場合に実用的ではないかもしれませんが、少なくとも概念的に知っておく価値はあります。私は最初にこの論文でそれについて読んだ。

トリックは、sinc補間によって均一なサンプルから既に再構築された非均一なサンプルのセットを考慮することです。論文の表記に従って:

yt=k=1NykTπtkT/TπtkT/T=k=1NykTsnctkTT

これにより、各不均一サンプルに1組の線形方程式が提供されることに注意してください。未知数は等間隔のサンプルです。y k T ytykT

[yt0yt1ytm]=[snct0TTsnct02TTsnct0nTTsnct1TTsnct12TTsnct1nTTsnctmTTsnctm2TTsnctmnTT][yTy2TynT]

上記の方程式で、は未知の均一なサンプルの数、は均一なサンプルレートの逆数、は不均一なサンプルの数(よりも大きい場合があります)です。そのシステムの最小二乗解を計算することにより、均一なサンプルを再構築できます。技術的には、不均一なサンプルのみが必要ですが、それらが時間内にどのように「散乱」するかに応じて、補間行列はひどく悪条件になる可能性があります。その場合、通常、より不均一なサンプルを使用すると役立ちます。T m n nnTmnn

おもちゃの例として、上記の方法と緩やかにジッターされたグリッドでの3次スプライン補間の比較(numpyを使用)を示します。

不均一なサンプルのSinc対3次スプライン再構成

(上記のプロットを再現するコードは、この回答の最後に含まれています)

言われていることはすべて、高品質で堅牢な方法の場合、次の論文のいずれかから始めるのがおそらくより適切でしょう。

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()

素晴らしいメソッドとコード。しかし、いくつかのドロップアウト(たとえば[0 1-3 4 8] T)がある場合、これはOPの問題だと思いますが、行列のsincはすべて0ではありませんか?もちろん、それを修正する方法はありますが。tj=jT
デニス

私が理解しているように、OPの質問は、ドロップされたサンプルや遅延したサンプルについてです。この方法は基本的に方程式の過剰決定系であるため、ドロップされたサンプルは不明としてのみ表示されます(値が0のデータポイントとしては表示されません)。それとも、それはあなたが求めているものではありませんか?
データガイスト

がすべて整数(T = 1)の場合はどうなりますか?データポイント[ ]があるとします。非ゼロ整数のセット、たとえば{-1 1}または{-2 -1 1 2}; 補間ではありませんにかかわらず、 -または私は何かを見逃していますか? J Y j個の J J Y 0 = 0 、Y JtjjyjjJy0=0yj
デニス

サンプルレートがまったく同じ場合(欠損ポイントがある場合)、補間行列はスパースになります(各出力が1つの入力のみに依存するため)。一般に、不均一なサンプルの平均サンプルレートは、均一な再構成レートよりも大きい必要があります。言い換えると、「ギャップを埋める」ために低いレートで再構築する必要があります(例ではT> 1)。私はあなたのポイントを見る。
データガイスト

2
このような答えは純金です。
アーメドファシ

6

これは、非同期のサンプルレート変換の問題のように聞こえます。あるサンプルレートから別のサンプルレートに変換するには、sinc補間を実行して信号の連続時間表現を計算し、新しいサンプルレートでリサンプリングします。あなたがしていることは大した違いはありません。サンプル時間を固定するには、信号をリサンプリングする必要があります。

連続時間信号は、各サンプルをsinc関数で畳み込むことにより計算できます。sinc関数は無限に続くため、実用的な有限長のウィンドウ化されたsincのような、より実用的なものを使用します。扱いにくい部分は、サンプルが時間内に移動するため、リサンプリング時に各サンプルに異なる位相オフセットを持つsincを使用する必要がある場合があることです。

サンプリングされた信号からの連続時間信号:

バツt=n=バツ[n]snctnTsTs

どこあなたのサンプル時間です。ただし、あなたの場合、サンプル時間は固定されていません。したがって、そのサンプルのサンプル時間に置き換える必要があると思います。Ts

バツt=n=バツ[n]snctnTs[n]Ts[n]

これから、信号をリサンプリングできます。

y[n]=バツnTns

ここで、は目的のサンプル時間です。Tns

すべてをまとめると、次のようになります。

y[m]=n=バツ[n]sncmTnsnTs[n]Ts[n]

これは因果関係も扱いやすいものでもないため、sinc関数は有限サポートの関数に置き換えられ、それに応じて合計の制限が調整されます。

kernel(t)をウィンドウ化されたsincまたは長さ2kの他の同様の関数とします:

y[m]=n=kkバツ[n]kernelmTnsnTs[n]Ts[n]

これが役立つことを願っていますが、途中でミスをした可能性があり、少し数学を集中させるかもしれません。詳細については、サンプルレートの変換を調査することをお勧めします。ここの他の誰かがより良い説明や解決策を提供できるかもしれません。


sinc関数を使用して信号の連続バージョンを再構築するには、サンプルが等間隔である必要があるため、sinc関数は任意のサンプル間隔に適応する必要があります。実装がかなり難しい場合があります。
user2718

ええ、これは正確にここで見られるようにすることはあまり効率的ではありません。異なるサンプル時間ごとに新しいカーネル係数を計算する必要があります。ただし、いくつかのカーネルのコレクションを計算し、時間をこれらの1つに量子化することができます。量子化誤差に関連してパフォーマンスが低下します。
ジェイコブ

また、単一のsincルックアップテーブルを事前計算して、そのルックアップテーブルのポイント間を補間することもできます。
JMS

5

ジェイコブの答えは非常に有効だと思います。

歪みを導入するという点でおそらくあまり良くないより簡単な方法は、多項式補間を行うことです。任意の時間サンプルから任意の時間にサンプルを生成するために、線形補間(簡単、良い信号パフォーマンスではない)またはキュービックスプライン(それほど難しくない、優れた信号パフォーマンス)を使用します。


1
あなたの答えは、ジェイコブよりも実装がはるかに簡単だと思われるので、最初にそれを使いました。動作しているようですが、まだ完全なテストセットを実行していません。
FigBug

1
@FigBug-時間がある場合は、最終的な解決策としてコメントを追加します。
user2718

2


Nnear

Nnear
y1y1
y0y1+y1/2
[バツy]バツ=0
y0y
[バツy]
a+bバツy0a
同じように、2次、3次、サイン-コサインに適合できます。



2πftf


4つまたは6つまたは8つの近隣との線形補間は、データに対して十分に機能する可能性があります。
sincのようなスプラインに飛び込む前に、あなたが完全に理解している方法から始めることをお勧めします...


別のまったく異なる方法は、 逆距離重み付けです。実装は簡単で(SOのidw-interpolation-with-pythonを参照)、2d 3d以上でも動作しますが、理論的に分析するのは難しいです。

(もちろん、NO単一の補間方法は、可能性の組み合わせの無数合うことができない
。実際に起こる[ノイズ信号は、エラーメトリック、テスト機能を】
テスト機能よりも、世界のその他の方法は、より多くのノブである。
それにもかかわらずギャラリーメソッドとテスト関数の組み合わせが役立つかもしれません。)


1

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

0

エキゾチックな処理を行う前に、このような単純なものを試すことができます(擬似コード-補間なし、しかし追加可能)

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]
   }
}

0

私見Datageistの答えは正しいですが、ジェイコブの答えは正しくありません。これを確認する簡単な方法は、datageistの推奨アルゴリズムが元のサンプルを補間することを保証していることです(無限の数値精度を想定しています)が、ジェイコブの答えはそうではありません。

  • 均一なサンプリングの場合、sinc関数のセットは直交します。シフトされた各sinc関数が入力サンプルに対して離散化される場合、それらは無限の単位行列を形成します。これは、n = 0を除くすべてのnについてsin(n pi)/(n pi)がゼロだからです。
  • ただし、この特性を単純に非一様なケースに外挿することはできません。入力サンプルに対して離散化された同様のsinc関数のセットは、自明でない行列を生成します。したがって、周囲のサンプルからの寄与はゼロではなく、再構築は入力サンプルを介して補間されなくなります。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.