Проблемы с корреляцией (обнаружение смещения) — мощность сигнала сосредоточена на границе домена

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

Я отслеживаю линии, сопоставляя каждую строку матрицы со строкой ниже и беря максимум корреляции для вычисления смещения. Это работает очень хорошо, ЗА ИСКЛЮЧЕНИЕМ случаев, когда сигналы находятся на краю домена. Это просто дает 0. Я подозреваю, что это потому, что выгодно просто добавлять на место, а не сдвигать 0 к краю. Вот несколько примеров сигналов, которые вызывают проблему. Эти сигналы не имеют нулевого среднего, но они есть, когда я коррелирую (я вычитаю среднее значение). Я получаю правильное смещение для третьего изображения, но не для первых двух.

Образец плохого сигнала 1

Образец плохого сигнала 2

Хороший сигнал 1

Вот мой код корреляции

x0 -= mean(x0)
x1 -= mean(x1)
x0 /= max(x0)
x1 /= max(x1)


c = signal.correlate(x1, x0, mode='full')
m = interp_peak_offset(c)
foffset =(m - len(x0) + 1) * (f[2] - f[1])

Я пробовал обрезать один из сигналов по 20 сэмплов с каждой стороны, коррелировать градиент сигнала и некоторые другие шаткие методы, но безуспешно...

Любая помощь приветствуется! Большое спасибо!


person Tyler Klein    schedule 22.08.2018    source источник
comment
Может корреляция не правильный подход? Пробовали ли вы решить простую задачу оптимизации? Минимизируйте квадратную разницу или абсолютную разницу.   -  person Cris Luengo    schedule 22.08.2018
comment
не могли бы вы загрузить сигнал?   -  person Gideon Kogan    schedule 26.08.2018
comment
@crisLuengo В итоге я использовал эту технику, и она прекрасно сработала. Я минимизировал среднюю абсолютную разницу (разность абс/количество точек, перекрывающихся в этой точке)   -  person Tyler Klein    schedule 05.11.2018
comment
Превосходно! Могу я предложить вам написать ответ на свой вопрос? Думаю, будущим посетителям будет полезно узнать, как вы решили эту проблему.   -  person Cris Luengo    schedule 05.11.2018


Ответы (2)


Вместо того, чтобы искать максимальную амплитуду, вы должны искать разность фаз. Этого можно добиться с помощью метода PHAT (Phase Transform):

def PHAT(x, y, fs, nperseg=50):
    f, pxy = csd(x, y, fs=1.0, nperseg=nperseg, return_onesided=False)
    pxy_phase = np.divide(pxy, np.abs(pxy))
    gcc_fun = np.real(ifft(pxy_phase))  # generelized cross correlation.
    TDOA = np.argmax(gcc_fun) / float(fs)
    return TDOA
person Gideon Kogan    schedule 26.08.2018

В итоге я минимизировал среднюю абсолютную разницу между двумя векторами. Для каждого временного сдвига я вычислял абсолютную разницу/количество точек перекрытия. Вот моя функция, которая делает это

def offset_using_diff(x0, x1, f):
#Finds the offset of x0 from x1 such that x0(f) ~ x1(f - foffset). Does so by 
#minimizing the average absolute difference between the two signals, with one signal 
#shifted.
#In other words, we minimize |x0 - x1|/N where N is the number of points overlapping 
#between x1 and the shifted version of x0

#Args:
#    x0,x1 (vector): data
#    f (vector): frequency vector

#Returns:
#   foffset (float): frequency offset

OMAX = min(len(x0) // 2, 100) # max offset in samples

dvec = zeros((2 * OMAX,))
offsetvec = arange(-OMAX + 1, OMAX + 1)

y0 = x0.copy()
y1 = x1.copy()

y0 -= min(y0)
y1 -= min(y1)

y0 = pad(y0, (100, 100), 'constant', constant_values=(0, 0))
y1 = pad(y1, (100, 100), 'constant', constant_values=(0, 0))

for i, offset in enumerate(offsetvec):
    d0 = roll(y0, offset)
    d1 = y1

    iinds1 = d0 != 0
    iinds2 = d1 != 0
    iinds = logical_and(iinds1, iinds2)
    d0 = d0[iinds]
    d1 = d1[iinds]

    diff = d0 - d1
    dvec[i] = sum(abs(diff))/len(d0)

m = interp_peak_offset(-1*dvec)
foffset = (m - OMAX + 1)*(f[2]-f[1])
return foffset
person Tyler Klein    schedule 05.11.2018