Что такое алгоритм для повторной выборки с переменной скоростью до фиксированной?


27

У меня есть датчик, который сообщает о своих показаниях с отметкой времени и значением. Тем не менее, он не генерирует показания с фиксированной скоростью.

Мне трудно работать с данными с переменной скоростью. Большинство фильтров ожидают фиксированную частоту дискретизации. Рисовать графики проще с фиксированной частотой дискретизации.

Существует ли алгоритм для повторной выборки с переменной частотой дискретизации до фиксированной частоты дискретизации?


Это кросс-пост от программистов. Мне сказали, что это лучшее место, чтобы спросить. programmers.stackexchange.com/questions/193795/…
FigBug

Что определяет, когда датчик сообщит о чтении? Отправляет ли чтение только тогда, когда оно меняется? Простой подход состоит в том, чтобы выбрать «интервал виртуальной выборки» (T), который просто меньше, чем кратчайшее время между генерируемыми показаниями. При вводе алгоритма сохраните только последнее зарегистрированное чтение (CurrentReading). На выходе алгоритма сообщайте CurrentReading как «новый образец» каждые T секунд, чтобы служба фильтрации или построения графиков получала показания с постоянной скоростью (каждые T секунд). Не знаю, достаточно ли это в вашем случае.
user2718

Он пытается сделать выборку каждые 5 мс или 10 мс. Но это задача с низким приоритетом, поэтому она может быть пропущена или отложена. У меня время с точностью до 1 мс. Обработка выполняется на ПК, а не в режиме реального времени, поэтому медленный алгоритм подходит, если его проще реализовать.
FigBug

1
Вы смотрели на реконструкцию Фурье? Существует преобразование Фурье на основе неравномерно выбранных данных. Обычный подход состоит в том, чтобы преобразовать изображение Фурье обратно в равномерно выбранную временную область.
mbaitoff

3
Знаете ли вы какие-либо характеристики базового сигнала, который вы используете? Если нерегулярно расположенные данные все еще имеют достаточно высокую частоту дискретизации по сравнению с шириной полосы измеряемого сигнала, то что-то простое, например, полиномиальная интерполяция в равномерно распределенную временную сетку, может работать нормально.
Джейсон Р

Ответы:


21

Самый простой подход - это выполнить некоторую сплайн-интерполяцию, как предлагает Джим Клэй (линейный или другой). Однако, если у вас есть возможность пакетной обработки, и особенно если у вас есть переопределенный набор неоднородных выборок, есть алгоритм «идеальной реконструкции», который чрезвычайно элегантен. По численным причинам это может быть не практичным во всех случаях, но, по крайней мере, стоит знать об этом концептуально. Я впервые прочитал об этом в этой статье .

Хитрость заключается в том, чтобы рассматривать ваш набор неоднородных выборок как уже восстановленный из однородных выборок путем синхрополяции . Следуя обозначениям в статье:

Y(T)знак равноΣКзнак равно1NY(КT)грех(π(T-КT)/T)π(T-КT)/Tзнак равноΣКзнак равно1NY(КT)sяNс(T-КTT),

Обратите внимание, что это обеспечивает набор линейных уравнений, по одному для каждой неоднородной выборки , где неизвестными являются одинаково расположенные выборки y ( k T ) , например:Y(T)Y(КT)

[Y(T0)Y(T1)Y(Tм)]знак равно[sяNс(T0-TT)sяNс(T0-2TT)sяNс(T0-NTT)sяNс(T1-TT)sяNс(T1-2TT)sяNс(T1-NTT)sяNс(Tм-TT)sяNс(Tм-2TT)sяNс(Tм-NTT)][Y(T)Y(2T)Y(NT)],

В приведенном выше уравнении - это число неизвестных однородных выборок, T - это обратная величина равномерной частоты дискретизации, а m - количество неоднородных выборок (которое может быть больше, чем n ). Вычисляя решение наименьших квадратов этой системы, можно восстановить однородные выборки. Технически, необходимы только n неоднородных выборок, но в зависимости от того, насколько они «разбросаны» во времени, интерполяционная матрица может быть ужасно плохо обусловлена . В этом случае обычно помогает использование большего количества неоднородных образцов.NTмNN

В качестве игрушечного примера, вот сравнение (с использованием numpy ) вышеупомянутого метода и интерполяции кубического сплайна на сетке с мягким волнением:

Синк против кубической сплайн реконструкции неоднородных образцов

(Код для воспроизведения приведенного выше сюжета приведен в конце этого ответа)

Все это, как говорится, для качественных и надежных методов, начиная с чего-то в одной из следующих статей, вероятно, будет более уместным

A. Aldroubi и 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()

TJзнак равноJT

Насколько я понимаю, вопрос ОП касается образцов, которые отброшены и / или задержаны. Этот метод представляет собой просто переопределенную систему уравнений, поэтому отброшенные выборки отображаются только как неизвестные (а не как точки данных со значением 0). Или, может быть, это не то, что вы спрашиваете?
Datageist

TJJ,YJJJY0знак равно0YJ

Если частоты дискретизации абсолютно идентичны (с отсутствующими точками), то матрица интерполяции будет разреженной (поскольку каждый выход зависит только от одного входа). В целом, средняя частота дискретизации неоднородных выборок должна быть больше, чем равномерная частота реконструкции. Другими словами, вам нужно будет реконструировать с более низкой скоростью, чтобы «заполнить пробелы» (T> 1 для вашего примера). Я понимаю вашу точку зрения, хотя.
Datageist

2
Подобные ответы - чистое золото.
Ахмед Фасих

6

Это звучит как проблема асинхронного преобразования частоты дискретизации. Чтобы преобразовать одну частоту дискретизации в другую, мы можем вычислить непрерывное временное представление сигнала, выполнив интерполяцию sinc, а затем выполнить повторную выборку с нашей новой частотой дискретизации. То, что вы делаете, не сильно отличается. Вам необходимо повторно сэмплировать ваш сигнал, чтобы иметь фиксированное время сэмплирования.

Непрерывный сигнал времени может быть рассчитан путем свертки каждого образца с функцией sinc. Поскольку функция sinc продолжается неопределенно долго, мы используем что-то более практичное, например, оконный sinc практической конечной длины. Сложность заключается в том, что, поскольку ваши сэмплы перемещаются во времени, при повторной дискретизации для каждого сэмпла может потребоваться сигнал с другим фазовым сдвигом.

Непрерывный сигнал времени из дискретизированного сигнала:

Икс(T)знак равноΣNзнак равно-Икс[N]sяNс(T-NTsTs)

Ts

Икс(T)знак равноΣNзнак равно-Икс[N]sяNс(T-NTs[N]Ts[N])

Из этого вы можете повторно сэмплировать сигнал:

Y[N]знак равноИкс(NTNs

TNs

Собрав все воедино, вы получите:

Y[м]знак равноΣNзнак равно-Икс[N]sяNс(мTNs-NTs[N]Ts[N])

Так как это не является причинно-следственной или поддающейся объяснению, функцию sinc можно заменить функцией конечной поддержки и соответствующим образом скорректировать пределы суммирования.

Пусть kernel (t) будет оконным sinc или другой подобной функцией длины 2k, тогда:

Y[м]знак равноΣNзнак равно-ККИкс[N]КерNеL(мTNs-NTs[N]Ts[N])

Я надеюсь, что это помогает ..., но я мог ошибиться, и это может быть немного интенсивным математикой. Я бы порекомендовал изучить преобразование частоты дискретизации для получения дополнительной информации. Может быть, кто-то еще мог бы дать лучшее объяснение или решение.


Использование функции sinc для восстановления непрерывной версии сигнала требует, чтобы сэмплы были расположены на одинаковом расстоянии, поэтому функция sinc должна будет адаптироваться к произвольному интервалу сэмплов. Может быть довольно сложно реализовать.
user2718

да, это было бы не очень эффективно делать именно так, как показано здесь. Это потребует вычисления новых коэффициентов ядра для каждого отдельного времени выборки. Однако можно вычислить набор из нескольких ядер, а время можно измерить для одного из них. Там будет снижение производительности по сравнению с ошибкой квантования.
Джейкоб

Вы также можете предварительно вычислить одну справочную таблицу sinc и выполнить интерполяцию между точками этой справочной таблицы.
JMS

5

Я думаю, что ответ Джейкоба очень выполним.

Более простой метод, который, вероятно, не так хорош с точки зрения введения искажения, - это выполнить полиномиальную интерполяцию. Я бы использовал линейную интерполяцию (простая, но не с хорошей производительностью сигнала) или кубические сплайны (но не слишком жесткие, с лучшей производительностью сигнала) для получения выборок в любое время, которое вы хотите из выборок произвольного времени.


1
Твой ответ кажется намного проще для реализации, чем у Джейкоба, поэтому я пошел с ним первым. Кажется, это работает, но я еще не выполнил полный набор тестов.
FigBug

1
@FigBug -Если у вас есть время, добавьте комментарий с окончательным решением.
user2718

2


NNеaр 2 4 6 ...
2) класс используемых базовых функций: линейный, полиномиальный, синус-косинус (Фурье), кусочно-кубический (B-сплайн или интерполирующий сплайн), подобный sinc ...
(Вариант 0 - использовать ли чужой метод и код или делать самому).

NNеaр
Y-1Y1 ]:
Y0~(Y-1+Y1)/2
[Икся,Yя]Иксязнак равно0
Y0~Yя
[Икся,Yя] :
a+бИксY0~a .
Можно подобрать квадратики, кубики, синус-косинусы ... таким же образом.



2πеTе = 0,25: 1 0 -1 0 1 0 -1 0 ...
2 соседа любой точки, в среднем равной 0, ужасно.
4 соседа: среднее значение [1 0 (отсутствует -1) 0 1] = 1/2, ужасно.
(Попробуйте использовать фильтр с 4 соседями [-1 3 3 -1] / 4.)

Линейная взаимосвязь с 4, 6 или 8 соседями может работать достаточно хорошо для ваших данных.
Я бы посоветовал начать с метода, который вы хорошо понимаете, прежде чем погрузиться в сплайны, похожие на синки ... хотя они тоже могут быть забавными


Другой, совершенно другой метод - это обратное взвешивание . Его легко реализовать (см. Idw-interpolation-with-python для SO), он работает в 2d 3d и выше, но теоретически его сложно анализировать.

(Не очевидно, NO один метод интерполяции может возможно соответствовать несметным комбинациям
[сигнал, шум, ошибки метрики, тест функция] , которые происходят в действительности.
Есть несколько методов в мире, с большим количеством кнопок, чем тест - функции.
Тем не менее в галерее методов и тестовых функций могут быть полезны.)


1

Если вы работаете с Matlab, вы можете сделать это, работая с сериями времени.

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 дискретизируется по входным выборкам, они образуют бесконечную единичную матрицу. Это потому, что sin (n pi) / (n pi) равен нулю для всех n, кроме n = 0.
  • Однако это свойство нельзя просто экстраполировать на неоднородный случай: подобный набор функций sinc, дискретизированный по входным выборкам, даст нетривиальную матрицу. Следовательно, вклады от окружающих выборок не будут равны нулю, и реконструкция больше не будет интерполировать входные выборки.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.