Apa yang dimaksud dengan algoritma untuk sampel ulang dari tingkat variabel ke tarif tetap?


27

Saya memiliki sensor yang melaporkan pembacaannya dengan cap waktu dan nilai. Namun, itu tidak menghasilkan bacaan pada tingkat yang tetap.

Saya menemukan data tingkat variabel sulit untuk ditangani. Sebagian besar filter mengharapkan tingkat sampel tetap. Menggambar grafik lebih mudah dengan laju sampel tetap juga.

Apakah ada algoritma untuk melakukan sampel ulang dari laju sampel variabel ke laju sampel tetap?


Ini adalah pos silang dari programmer. Saya diberitahu ini adalah tempat yang lebih baik untuk bertanya. programmers.stackexchange.com/questions/193795/…
FigBug

Apa yang menentukan kapan sensor akan melaporkan pembacaan? Apakah itu mengirim bacaan hanya ketika bacaan berubah? Pendekatan sederhana adalah dengan memilih "interval sampel virtual" (T) yang hanya lebih kecil dari waktu singkat antara pembacaan yang dihasilkan. Pada input algoritme, simpan hanya bacaan yang dilaporkan terakhir (CurrentReading). Pada hasil algoritme, laporkan CurrentReading sebagai "sampel baru" setiap detik T sehingga layanan filter atau grafik menerima bacaan dengan kecepatan konstan (setiap detik T). Tidak tahu apakah ini cukup untuk Anda.
user2718

Mencoba mencoba setiap 5 ms atau 10 ms. Tetapi ini adalah tugas dengan prioritas rendah, sehingga mungkin terlewat atau tertunda. Saya memiliki waktu yang akurat hingga 1 ms. Pemrosesan dilakukan pada PC, bukan dalam waktu nyata, sehingga algoritma yang lambat tidak masalah jika lebih mudah diterapkan.
FigBug

1
Sudahkah Anda melihat rekonstruksi empat tingkat? Ada transformasi fourier berdasarkan data sampel tidak merata. Aoproach yang biasa adalah mengubah gambar fourier kembali ke domain waktu yang disampel secara merata.
mbaitoff

3
Apakah Anda tahu karakteristik sinyal yang mendasari bahwa Anda mengambil sampel? Jika data spasi tidak teratur masih pada tingkat sampel yang cukup tinggi dibandingkan dengan bandwidth sinyal yang diukur, maka sesuatu yang sederhana seperti interpolasi polinomial ke grid waktu yang berjarak sama mungkin bekerja dengan baik.
Jason R

Jawaban:


21

Pendekatan paling sederhana adalah dengan melakukan semacam interpolasi spline seperti yang disarankan Jim Clay (linier atau lainnya). Namun, jika Anda memiliki kemewahan pemrosesan batch, dan terutama jika Anda memiliki set sampel tidak seragam yang ditentukan secara berlebihan, ada algoritma "rekonstruksi sempurna" yang sangat elegan. Untuk alasan numerik, mungkin tidak praktis dalam semua kasus, tetapi setidaknya perlu diketahui secara konseptual. Saya pertama kali membacanya di makalah ini .

Caranya adalah dengan mempertimbangkan set sampel tidak seragam Anda yang telah direkonstruksi dari sampel yang seragam melalui interpolasi tulus . Mengikuti notasi di koran:

y(t)=k=1Ny(kT)sin(π(tkT)/T)π(tkT)/T=k=1Ny(kT)sinc(tkTT).

Perhatikan bahwa ini menyediakan satu set persamaan linear, satu untuk setiap sampel tidak seragam , di mana yang tidak diketahui adalah sampel dengan spasi yang sama , seperti:y(t)y(kT)

[y(t0)y(t1)y(tm)]=[sinc(t0TT)sinc(t02TT)sinc(t0nTT)sinc(t1TT)sinc(t12TT)sinc(t1nTT)sinc(tmTT)sinc(tm2TT)sinc(tmnTT)][y(T)y(2T)y(nT)].

Dalam persamaan di atas, adalah jumlah sampel seragam yang tidak diketahui, adalah kebalikan dari laju sampel seragam, dan adalah jumlah sampel tidak seragam (yang mungkin lebih besar dari ). Dengan menghitung solusi kuadrat terkecil dari sistem itu, sampel yang seragam dapat direkonstruksi. Secara teknis, hanya sampel tidak seragam yang diperlukan, tetapi tergantung pada seberapa "tersebar" mereka dalam waktu, matriks interpolasi mungkin sangat buruk dikondisikan . Ketika itu masalahnya, menggunakan lebih banyak sampel yang tidak seragam biasanya membantu.nTmnn

Sebagai contoh mainan, inilah perbandingan (menggunakan numpy ) antara metode di atas dan interpolasi spline kubik pada kisi yang agak gugup:

Rekonstruksi Sinc vs Cubic Spline dari Sampel Tidak Serata

(Kode untuk mereproduksi plot di atas termasuk di akhir jawaban ini)

Semua yang dikatakan, untuk metode berkualitas tinggi, kuat, dimulai dengan sesuatu di salah satu makalah berikut mungkin akan lebih tepat:

A. Aldroubi dan Karlheinz Grochenig, Pengambilan sampel dan rekonstruksi yang tidak seragam dalam ruang-ruang yang tidak berubah , SIAM Rev., 2001, no. 4, 585-620. ( tautan pdf ).

K. Grochenig dan H. Schwab, Metode rekonstruksi lokal cepat untuk pengambilan sampel tidak seragam di ruang shift-invariant , 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()

Metode dan kode yang bagus. Tetapi untuk dengan beberapa dropout (misalnya [0 1 - 3 4 5 - 7 8] T), yang saya pikir adalah pertanyaan OP, bukankah sinc dalam matriks semuanya adalah 0? Tentu ada cara untuk memperbaikinya, tetapi. tj=jT
denis

Seperti yang saya pahami, pertanyaan OP adalah tentang sampel yang dijatuhkan dan / atau ditunda. Metode ini pada dasarnya hanya merupakan sistem persamaan yang ditentukan secara berlebihan, sehingga sampel yang dijatuhkan hanya muncul sebagai tidak diketahui (bukan sebagai titik data dengan nilai 0). Atau mungkin bukan itu yang Anda tanyakan?
datageist

Apa yang terjadi jika semuanya bilangan bulat (T = 1)? Katakanlah kita memiliki titik data [ ] untuk , satu set bilangan bulat bukan nol misalnya {-1 1} atau {-2 -1 1 2}; bukankah interpolasi , terlepas dari - atau apakah saya melewatkan sesuatu? tjj,yjjJy0=0yj
denis

Jika laju sampel sama persis (dengan titik hilang), maka matriks interpolasi akan jarang (karena setiap output tergantung hanya pada satu input). Secara umum, rata-rata laju sampel dari sampel tidak seragam perlu lebih besar daripada laju rekonstruksi seragam. Dengan kata lain, Anda harus merekonstruksi pada tingkat yang lebih rendah untuk "mengisi kesenjangan" (T> 1 sebagai contoh Anda). Saya mengerti maksud Anda.
datageist

2
Jawaban seperti ini adalah emas murni.
Ahmed Fasih

6

Ini terdengar seperti masalah konversi laju sampel asinkron. Untuk mengonversi dari satu laju sampel ke yang lain, kami dapat menghitung representasi waktu kontinyu dari sinyal dengan melakukan interpolasi tulus, lalu melakukan pengujian ulang pada laju sampel baru kami. Apa yang Anda lakukan tidak jauh berbeda. Anda perlu menguji ulang sinyal Anda untuk mendapatkan waktu sampel yang diperbaiki.

Sinyal waktu kontinu dapat dihitung dengan menggabungkan setiap sampel dengan fungsi sinc. Karena fungsi sinc berlanjut tanpa batas, kami menggunakan sesuatu yang lebih praktis seperti jendela berjendela dengan panjang yang praktis. Bagian yang sulit adalah bahwa karena sampel Anda bergerak dalam waktu, sinc dengan fase offset yang berbeda mungkin perlu digunakan untuk setiap sampel ketika melakukan resampling.

Sinyal waktu kontinu dari sinyal sampel:

x(t)=n=x[n]sinc(tnTsTs)

di mana adalah waktu sampel Anda. Namun, dalam kasus Anda, waktu sampel Anda tidak tetap. Jadi saya pikir Anda perlu menggantinya dengan waktu sampel di sampel itu.Ts

x(t)=n=x[n]sinc(tnTs[n]Ts[n])

Dari ini, Anda dapat menguji ulang sinyal:

y[n]=x(nTns )

di mana adalah waktu sampel yang diinginkan.Tns

Menyatukan semuanya Anda dapatkan:

y[m]=n=x[n]sinc(mTnsnTs[n]Ts[n])

Karena ini bukan sebab akibat atau dapat ditelusuri, fungsi sinc dapat diganti dengan fungsi dukungan yang terbatas dan batas penjumlahan disesuaikan sesuai.

Biarkan kernel (t) menjadi sinc jendela atau fungsi lain yang serupa dengan panjang 2k kemudian:

y[m]=n=kkx[n]kernel(mTnsnTs[n]Ts[n])

Saya harap ini membantu ..., tapi saya mungkin telah membuat kesalahan di sepanjang jalan dan mungkin sedikit intensif secara matematika. Saya akan merekomendasikan meneliti konversi laju sampel untuk informasi lebih lanjut. Mungkin orang lain di sini bisa memberikan penjelasan atau solusi yang lebih baik juga.


Menggunakan fungsi sinc untuk merekonstruksi versi kontinyu dari sinyal mengharuskan sampel ditempatkan dengan jarak yang sama, sehingga fungsi sinc harus beradaptasi dengan arbitrase spasi sampel. Bisa jadi agak sulit diimplementasikan.
user2718

ya, ini tidak akan sangat efisien untuk melakukan persis seperti yang terlihat di sini. Dibutuhkan penghitungan koefisien kernel baru untuk setiap waktu sampel yang berbeda. Namun, kumpulan beberapa kernel dapat dihitung, dan waktu dikuantifikasi dengan salah satunya. Akan ada hit kinerja relatif terhadap kesalahan kuantisasi.
Jacob

Anda juga bisa melakukan pre-compute satu tabel lookup tunggal dan menginterpolasi antara titik-titik tabel pencarian itu.
Jms

5

Saya pikir jawaban Yakub sangat bisa diterapkan.

Metode yang lebih mudah yang mungkin tidak begitu baik dalam hal memperkenalkan distorsi adalah dengan melakukan interpolasi polinomial. Saya akan menggunakan interpolasi linier (mudah, tidak sebagus kinerja sinyal-bijaksana) atau splines kubik (masih tidak terlalu keras, kinerja sinyal lebih baik) untuk menghasilkan sampel kapan saja Anda inginkan dari sampel waktu sewenang-wenang Anda.


1
Jawaban Anda tampaknya jauh lebih mudah diterapkan daripada jawaban Yakub, jadi saya sudah mengikutinya terlebih dahulu. Tampaknya berfungsi, tetapi saya belum menjalankan set lengkap tes.
FigBug

1
@ FigBug -Jika Anda punya waktu, tambahkan komentar dengan solusi final Anda.
user2718

2

(Sebulan kemudian) ada dua pilihan utama untuk setiap metode interpolasi:
1) jumlah titik data terdekat dengan titik yang hilang untuk digunakan, 2 4 6 ... 2) kelas fungsi basis yang digunakan: linear, polinomial, sine-cosine (Fourier), piecewise cubic (B-spline atau interpolasi spline), seperti-seperti ... (Pilihan 0 adalah apakah menggunakan metode dan kode orang lain, atau melakukannya sendiri).Nnear

Memasukkan garis lurus ke titik mudah: 2 poin [-1, ], [1, ]: Estimasi poin dengan rata-rata : rata-rata umum : lihat misalnya Numerical Recipes h. 781: paskan baris dan perkirakan . Seseorang dapat kuadrat, kubik, sinus-cosinus ... dengan cara yang sama.Nnear
y1y1
[ x i , y i ] x i = 0y0(y1+y1)/2
[xi,yi]xi=0
y i [ x i , y i ]y0yi
[xi,yi]
y 0aa+bxy0a

Saya mengerti bahwa Anda memiliki data dengan spasi yang sama dengan beberapa poin yang hilang, apakah itu benar?
Seberapa baik interpolasi linier berfungsi untuk kasus ini?
Baiklah, mari kita coba cos dengan = 0.25: 1 0 -1 0 1 0 -1 0 ... 2 tetangga dari setiap titik rata-rata ke 0, mengerikan. 4 tetangga: rata-rata [1 0 (hilang -1) 0 1] = 1/2, mengerikan. (Coba filter 4-tetangga [-1 3 3 -1] / 4 untuk ini.)f2πftf


Interplasi linear dengan 4 atau 6 atau 8 tetangga mungkin bekerja cukup baik untuk data Anda.
Saya sarankan memulai dengan metode yang Anda pahami sebelum menyelam ke splines, seperti-tulus ... meskipun itu bisa menyenangkan juga.


Metode lain yang sangat berbeda adalah pembobotan jarak terbalik . Sangat mudah untuk diimplementasikan (lihat idw-interpolasi-dengan-python pada SO), bekerja dalam 2d 3d dan juga, tetapi afaik sulit untuk dianalisis secara teoritis.

(Jelas, TIDAK ada metode interpolasi tunggal yang dapat cocok dengan zillions kombinasi
[sinyal, noise, metrik kesalahan, fungsi tes] yang terjadi dalam kenyataan.
Ada lebih banyak metode di dunia, dengan lebih banyak kenop, daripada fungsi pengujian.
Meskipun demikian galeri metode dan fungsi pengujian mungkin berguna.)


1

Jika Anda bekerja dengan matlab, Anda dapat melakukannya dengan bekerja dengan pengaturan waktu.

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

Sebelum Anda mulai melakukan beberapa pemrosesan eksotis Anda dapat mencoba sesuatu yang sederhana seperti ini (kode semu - tidak ada interpolasi, tetapi itu bisa ditambahkan)

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

Jawaban IMHO Datageist benar, jawaban Yakub tidak. Cara mudah untuk memverifikasi ini adalah bahwa algoritma yang disarankan datageist dijamin untuk diinterpolasi melalui sampel asli (dengan asumsi ketepatan angka tak terbatas), sedangkan jawaban Yakub tidak.

  • Untuk kasus pengambilan sampel yang seragam, rangkaian fungsi sinc adalah ortogonal: jika setiap fungsi sinc yang digeser diskritkan atas sampel input, mereka membentuk matriks identitas yang tak terbatas. Ini karena dosa (n pi) / (n pi) adalah nol untuk semua n kecuali n = 0.
  • Namun, properti ini tidak dapat dengan mudah diekstrapolasi ke kasus yang tidak seragam: seperangkat fungsi sinc yang sama, didiskritkan atas sampel input, akan menghasilkan matriks nontrivial. Oleh karena itu, kontribusi dari sampel di sekitarnya tidak akan nol, dan rekonstruksi tidak akan lagi diinterpolasi melalui sampel input.
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.