find time shift between two similar waveforms

前端 未结 6 1730
灰色年华
灰色年华 2020-12-04 11:34

I have to compare two time-vs-voltage waveforms. Because of the peculiarity of the sources of these waveforms, one of them can be a time shifted version of the other.

6条回答
  •  情书的邮戳
    2020-12-04 12:08

    This function is probably more efficient for real-valued signals. It uses rfft and zero pads the inputs to a power of 2 large enough to ensure linear (i.e. non-circular) correlation:

    def rfft_xcorr(x, y):
        M = len(x) + len(y) - 1
        N = 2 ** int(np.ceil(np.log2(M)))
        X = np.fft.rfft(x, N)
        Y = np.fft.rfft(y, N)
        cxy = np.fft.irfft(X * np.conj(Y))
        cxy = np.hstack((cxy[:len(x)], cxy[N-len(y)+1:]))
        return cxy
    

    The return value is length M = len(x) + len(y) - 1 (hacked together with hstack to remove the extra zeros from rounding up to a power of 2). The non-negative lags are cxy[0], cxy[1], ..., cxy[len(x)-1], while the negative lags are cxy[-1], cxy[-2], ..., cxy[-len(y)+1].

    To match a reference signal, I'd compute rfft_xcorr(x, ref) and look for the peak. For example:

    def match(x, ref):
        cxy = rfft_xcorr(x, ref)
        index = np.argmax(cxy)
        if index < len(x):
            return index
        else: # negative lag
            return index - len(cxy)   
    
    In [1]: ref = np.array([1,2,3,4,5])
    In [2]: x = np.hstack(([2,-3,9], 1.5 * ref, [0,3,8]))
    In [3]: match(x, ref)
    Out[3]: 3
    In [4]: x = np.hstack((1.5 * ref, [0,3,8], [2,-3,-9]))
    In [5]: match(x, ref)
    Out[5]: 0
    In [6]: x = np.hstack((1.5 * ref[1:], [0,3,8], [2,-3,-9,1]))
    In [7]: match(x, ref)
    Out[7]: -1
    

    It's not a robust way to match signals, but it is quick and easy.

提交回复
热议问题