为什么在填充输入之一时python scipy互相关不起作用 [英] Why python scipy cross correlation is not working when padding one of the inputs

查看:40
本文介绍了为什么在填充输入之一时python scipy互相关不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

scipy 互相关函数根本不适用于特定的一维数组,我不知道为什么.下面的代码演示了这个问题,只需尝试使用一个跟踪而不是另一个.

这个问题与

  • 绘制自然轨迹(代码中的第二个)

  • 解决方案

    请参阅下面 Paul Panzer 的回答和评论.

    原始代码的问题在于非零填充.

    当用非零值移动数组时,互相关值越来越高,峰值受到影响.下面的代码和图片演示了这种效果:

    <预类= 郎吡prettyprint-越权"> <代码>跟踪= np.array([0.51231204949426460,0.47472182808002383,0.48806029762272723,0.51352464310119930,0.58506742537603330,0.62993314829830390,0.57657927012749040,0.55369158834668990,0.56255864527226200,0.61576098682569510,0.62955418648769630,0.64236215760241170,0.69063835641941580,0.75073729780384960,0.86896478361172370,0.92216712516515690,0.91329988783884970,0.92807831604813670,0.99113300320800610,0.99999999999999990,0.91527040506699960,0.80098377331469030,0.71723934679539750,0.68275634764039450,0.65812563395824950,0.63250963159524040,0.59999708953480900,0.55172083058422660,0.54975037348965490,0.57011178351142090,0.52807534544936740])对于 np.arange(0, trace.min(), trace.min()/10) 中的 padding_value:left_padded_trace = np.pad(trace, (10, 0), mode='constant', constant_values=padding_value)center_padded_trace = np.pad(trace, (5, 5), mode='constant', constant_values=padding_value)相关性 = 信号.correlate(center_padded_trace, left_padded_trace, mode='full', method='fft')corr_peak_index = np.argmax(相关性)plt.figure(2)plt.subplot(211)plt.title('左填充痕迹')plt.xticks([])plt.plot(left_padded_trace)plt.subplot(212)plt.title('居中填充轨迹')plt.plot(center_padded_trace)plt.figure(3)plt.plot(范围(0,correlation.size),correlation)plt.plot([corr_peak_index], [correlation[corr_peak_index]], 'k+')plt.show()

    结果如下所示.可以看到,随着填充值的增加,相关峰值向中心移动.

    • 具有不同填充级别的跟踪,从 0 到最小值

      • 相关值和峰值

    解决方案

    不同之处在于您使用最小值进行填充,在第二次跟踪的情况下该最小值不为零.因此,您不能期望峰值随偏移量而移动.相反,您会得到移动的峰值曲线加上一个以最小值缩放的三角形.

    将 numpy 导入为 np从 scipy 导入信号导入 matplotlib.pyplot 作为 pltdef_main(offset=0,trace_idx=0):跟踪= [np.array([0.00000000000000001,0.00000000000000002,0.00000000000000001,0.00000000000000002,0.00000000000000001,0.00000000000000002,0.00000000000000001,0.00000000000000002,0.00000000000000001,0.00000000000000002,#下来步骤0.99999999999999998,0.99999999999999999,0.99999999999999998,0.99999999999999999,0.99999999999999998,0.99999999999999999,0.99999999999999998,0.99999999999999999,0.99999999999999998,0.99999999999999999,0.99999999999999998,#了步骤0.00000000000000001,0.00000000000000002,0.00000000000000001,0.00000000000000002,0.00000000000000001,0.00000000000000002,0.00000000000000001,0.00000000000000002,0.00000000000000001,0.00000000000000002]),#下来步骤np.array([0.51231204949426460,0.47472182808002383,0.48806029762272723,0.51352464310119930,0.58506742537603330,0.62993314829830390,0.57657927012749040,0.55369158834668990,0.56255864527226200,0.61576098682569510,0.62955418648769630,0.64236215760241170,0.69063835641941580,0.75073729780384960,0.86896478361172370,0.92216712516515690,0.91329988783884970,0.92807831604813670,0.99113300320800610,0.99999999999999990,0.91527040506699960,0.80098377331469030,0.71723934679539750,0.68275634764039450,0.65812563395824950,0.63250963159524040,0.59999708953480900,0.55172083058422660,0.54975037348965490,0.57011178351142090,0.52807534544936740])] [trace_idx]跟踪 += 偏移 - trace.min()left_padded_trace = np.pad(trace, (10, 0), mode='constant', constant_values=trace.min())center_padded_trace = np.pad(trace, (5, 5), mode='constant', constant_values=trace.min())right_padded_trace = np.pad(trace, (0, 10), mode='constant', constant_values=trace.min())相关性 1 = 信号.相关(center_padded_trace,left_padded_trace,mode='full',method='fft')相关性 2 = 信号.相关(center_padded_trace,center_padded_trace,mode='full',method='fft')相关性 3 = 信号.相关(center_padded_trace,right_padded_trace,mode='full',method='fft')corr_peak_index1 = np.argmax(correlation1)corr_max1 = np.max(correlation1)corr_peak_index2 = np.argmax(correlation2)corr_max2 = np.max(correlation2)corr_peak_index3 = np.argmax(correlation3)corr_max3 = np.max(correlation3)offset1 = corr_peak_index1-(center_padded_trace.size-1)offset2 = corr_peak_index2-(center_padded_trace.size-1)offset3 = corr_peak_index3-(center_padded_trace.size-1)返回偏移量1、偏移量2、偏移量3打印(Corr1:{},Corr2:{},Corr3:{}".格式(corr_peak_index1,corr_peak_index2,corr_peak_index3))打印(偏移量1:{},偏移量2:{},偏移量3:{}".格式(偏移量1,偏移量2,偏移量3))plt.figure(1)plt.subplot(311)plt.plot(range(0, center_padded_trace.size), center_padded_trace, 'r-',范围(offset1, left_padded_trace.size+offset1), left_padded_trace, 'b--',范围(0,correlation1.size),correlation1/corr_max1,'g-',[corr_peak_index1], [1], 'k+')plt.subplot(312)plt.plot(range(0, center_padded_trace.size), center_padded_trace, 'r-',范围(offset2,center_padded_trace.size+offset2),center_padded_trace,'b--',范围(0,correlation2.size),correlation2/corr_max2,'g-',[corr_peak_index2], [1], 'k+')plt.subplot(313)plt.plot(range(0, center_padded_trace.size), center_padded_trace, 'r-',范围(offset3, right_padded_trace.size+offset3), right_padded_trace, 'b--',范围(0,correlation3.size),correlation3/corr_max3,'g-',[corr_peak_index3], [1], 'k+')plt.show()x = np.arange(200)*0.01y1 = np.array([*map(_main, x)])y2 = np.array([*map(_main, x, np.ones(x.size,int))])plt.figure(1)plt.subplot(211)plt.title('合成')plt.plot(x,y1)plt.legend(('左移输入', '居中输入', '右移输入'))plt.subplot(212)plt.title('自然')plt.plot(x,y2)plt.ylabel('x-offset of result')plt.xlabel('y-offset')plt.savefig("summary.png")

    The scipy cross correlation function is simply not working for a specific 1d array and I cant figure out why. The code below demonstrate the problem, just try it with one trace and than the other.

    This question is a bit related to cross correlation and Python cross-correlation not returning correct shift

    #!/usr/bin/python3
    
    import numpy as np
    from scipy import signal
    import matplotlib.pyplot as plt
    
    def _main():
        """
        trace = np.array([0.00000000000000001, 0.00000000000000002, 0.00000000000000001, 0.00000000000000002, 0.00000000000000001, 0.00000000000000002, 0.00000000000000001, 0.00000000000000002, 0.00000000000000001, 0.00000000000000002, # down the step
                          0.99999999999999998, 0.99999999999999999, 0.99999999999999998, 0.99999999999999999, 0.99999999999999998, 0.99999999999999999, 0.99999999999999998, 0.99999999999999999, 0.99999999999999998, 0.99999999999999999, 0.99999999999999998, # up the step
                          0.00000000000000001, 0.00000000000000002, 0.00000000000000001, 0.00000000000000002, 0.00000000000000001, 0.00000000000000002, 0.00000000000000001, 0.00000000000000002, 0.00000000000000001, 0.00000000000000002]) # down the step
        """
        trace = np.array([0.51231204949426460, 0.47472182808002383, 0.48806029762272723, 0.51352464310119930, 0.58506742537603330, 0.62993314829830390, 0.57657927012749040, 0.55369158834668990, 0.56255864527226200, 0.61576098682569510,
                          0.62955418648769630, 0.64236215760241170, 0.69063835641941580, 0.75073729780384960, 0.86896478361172370, 0.92216712516515690, 0.91329988783884970, 0.92807831604813670, 0.99113300320800610, 0.99999999999999990, 0.91527040506699960, 
                          0.80098377331469030, 0.71723934679539750, 0.68275634764039450, 0.65812563395824950, 0.63250963159524040, 0.59999708953480900, 0.55172083058422660, 0.54975037348965490, 0.57011178351142090, 0.52807534544936740])
    
    
        left_padded_trace = np.pad(trace, (10, 0), mode='constant', constant_values=trace.min())
        center_padded_trace = np.pad(trace, (5, 5), mode='constant', constant_values=trace.min())
        right_padded_trace = np.pad(trace, (0, 10), mode='constant', constant_values=trace.min())
    
        correlation1 = signal.correlate(center_padded_trace, left_padded_trace, mode='full', method='fft')
        correlation2 = signal.correlate(center_padded_trace, center_padded_trace, mode='full', method='fft')
        correlation3 = signal.correlate(center_padded_trace, right_padded_trace, mode='full', method='fft')
    
        corr_peak_index1 = np.argmax(correlation1)
        corr_max1 = np.max(correlation1)
    
        corr_peak_index2 = np.argmax(correlation2)
        corr_max2 = np.max(correlation2)
    
        corr_peak_index3 = np.argmax(correlation3)
        corr_max3 = np.max(correlation3)
    
        offset1 = corr_peak_index1-(center_padded_trace.size-1)
        offset2 = corr_peak_index2-(center_padded_trace.size-1)
        offset3 = corr_peak_index3-(center_padded_trace.size-1)
    
        print("Corr1: {}, Corr2: {}, Corr3: {}".format(corr_peak_index1, corr_peak_index2, corr_peak_index3))
        print("Offset1: {}, Offset2: {}, Offset3: {}".format(offset1, offset2, offset3))
    
        plt.figure(1)
    
        plt.subplot(311)
        plt.plot(range(0, center_padded_trace.size), center_padded_trace, 'r-',
                range(offset1, left_padded_trace.size+offset1), left_padded_trace, 'b--',
                range(0, correlation1.size), correlation1/corr_max1, 'g-',
                [corr_peak_index1], [1], 'k+')
    
        plt.subplot(312)
        plt.plot(range(0, center_padded_trace.size), center_padded_trace, 'r-',
                range(offset2, center_padded_trace.size+offset2), center_padded_trace, 'b--',
                range(0, correlation2.size), correlation2/corr_max2, 'g-',
                [corr_peak_index2], [1], 'k+')
    
        plt.subplot(313)
        plt.plot(range(0, center_padded_trace.size), center_padded_trace, 'r-',
                range(offset3, right_padded_trace.size+offset3), right_padded_trace, 'b--',
                range(0, correlation3.size), correlation3/corr_max3, 'g-',
                [corr_peak_index3], [1], 'k+')
    
        plt.show()
    
    

    Since the shift added by padding is the same and the only difference is the change on the input trace, the results in terms of shift and alignment from the correlation should be the same but they are not.

    For the first trace (more synthetic step) the correlations and offsets are: (1 is the left padded, 2 is the centered and 3 is the right padded)

    • Corr1: 35, Corr2: 40, Corr3: 45
    • Offset1: -5, Offset2: 0, Offset3: 5

    For the second trace (more natural), the

    • Corr1: 40, Corr2: 40, Corr3: 40
    • Offset1: 0, Offset2: 0, Offset3: 0

    Follows the plots:

    • Plot for the synthetic trace (first in the code)

    • Plot for the natural trace (second in the code)

    Solution

    See answer and comments from Paul Panzer below.

    The problem is with the original code is with the non zero padding.

    When shifting the array with non zero values, the cross correlation value gets increasingly higher and the peak gets affected. The following code and images demonstrates this effect:

        trace = np.array([0.51231204949426460, 0.47472182808002383, 0.48806029762272723, 0.51352464310119930, 0.58506742537603330, 0.62993314829830390, 0.57657927012749040, 0.55369158834668990, 0.56255864527226200, 0.61576098682569510, 0.62955418648769630, 0.64236215760241170, 0.69063835641941580, 0.75073729780384960, 0.86896478361172370, 0.92216712516515690, 0.91329988783884970, 0.92807831604813670, 0.99113300320800610, 0.99999999999999990, 0.91527040506699960, 0.80098377331469030, 0.71723934679539750, 0.68275634764039450, 0.65812563395824950, 0.63250963159524040, 0.59999708953480900, 0.55172083058422660, 0.54975037348965490, 0.57011178351142090, 0.52807534544936740])
    
        for padding_value in np.arange(0, trace.min(), trace.min()/10):
            left_padded_trace = np.pad(trace, (10, 0), mode='constant', constant_values=padding_value)
            center_padded_trace = np.pad(trace, (5, 5), mode='constant', constant_values=padding_value)
    
            correlation = signal.correlate(center_padded_trace, left_padded_trace, mode='full', method='fft')
    
            corr_peak_index = np.argmax(correlation)
    
            plt.figure(2)
            plt.subplot(211)
            plt.title('Left Padded Trace')
            plt.xticks([])
            plt.plot(left_padded_trace)
            plt.subplot(212)
            plt.title('Centered Padded Trace')
            plt.plot(center_padded_trace)
    
            plt.figure(3)
            plt.plot(range(0, correlation.size), correlation)
            plt.plot([corr_peak_index], [correlation[corr_peak_index]], 'k+')
    
        plt.show()
    

    The results are presented below. One can see that, as the padding value increases, the correlation peak moves to the center.

    • Traces with different padding levels, from 0 up to the minimum

      • Correlation values and peak

    解决方案

    The difference is explained by the fact that you are padding with the minimum which is not zero in case of the second trace. As a consequence you cannot expect the peak just to shift with the offset. Instead you get the shifted peak curve plus a triangle that scales with the minimum.

    import numpy as np
    from scipy import signal
    import matplotlib.pyplot as plt
    
    def _main(offset=0, trace_idx=0):
        trace = [np.array([0.00000000000000001, 0.00000000000000002, 0.00000000000000001, 0.00000000000000002, 0.00000000000000001, 0.00000000000000002, 0.00000000000000001, 0.00000000000000002, 0.00000000000000001, 0.00000000000000002, # down the step
                          0.99999999999999998, 0.99999999999999999, 0.99999999999999998, 0.99999999999999999, 0.99999999999999998, 0.99999999999999999, 0.99999999999999998, 0.99999999999999999, 0.99999999999999998, 0.99999999999999999, 0.99999999999999998, # up the step
                           0.00000000000000001, 0.00000000000000002, 0.00000000000000001, 0.00000000000000002, 0.00000000000000001, 0.00000000000000002, 0.00000000000000001, 0.00000000000000002, 0.00000000000000001, 0.00000000000000002]), # down the step
        np.array([0.51231204949426460, 0.47472182808002383, 0.48806029762272723, 0.51352464310119930, 0.58506742537603330, 0.62993314829830390, 0.57657927012749040, 0.55369158834668990, 0.56255864527226200, 0.61576098682569510,
                          0.62955418648769630, 0.64236215760241170, 0.69063835641941580, 0.75073729780384960, 0.86896478361172370, 0.92216712516515690, 0.91329988783884970, 0.92807831604813670, 0.99113300320800610, 0.99999999999999990, 0.91527040506699960, 
                          0.80098377331469030, 0.71723934679539750, 0.68275634764039450, 0.65812563395824950, 0.63250963159524040, 0.59999708953480900, 0.55172083058422660, 0.54975037348965490, 0.57011178351142090, 0.52807534544936740])][trace_idx]
    
        trace += offset - trace.min()
    
        left_padded_trace = np.pad(trace, (10, 0), mode='constant', constant_values=trace.min())
        center_padded_trace = np.pad(trace, (5, 5), mode='constant', constant_values=trace.min())
        right_padded_trace = np.pad(trace, (0, 10), mode='constant', constant_values=trace.min())
    
        correlation1 = signal.correlate(center_padded_trace, left_padded_trace, mode='full', method='fft')
        correlation2 = signal.correlate(center_padded_trace, center_padded_trace, mode='full', method='fft')
        correlation3 = signal.correlate(center_padded_trace, right_padded_trace, mode='full', method='fft')
    
        corr_peak_index1 = np.argmax(correlation1)
        corr_max1 = np.max(correlation1)
    
        corr_peak_index2 = np.argmax(correlation2)
        corr_max2 = np.max(correlation2)
    
        corr_peak_index3 = np.argmax(correlation3)
        corr_max3 = np.max(correlation3)
    
        offset1 = corr_peak_index1-(center_padded_trace.size-1)
        offset2 = corr_peak_index2-(center_padded_trace.size-1)
        offset3 = corr_peak_index3-(center_padded_trace.size-1)
    
        return offset1, offset2, offset3
    
        print("Corr1: {}, Corr2: {}, Corr3: {}".format(corr_peak_index1, corr_peak_index2, corr_peak_index3))
        print("Offset1: {}, Offset2: {}, Offset3: {}".format(offset1, offset2, offset3))
    
        plt.figure(1)
    
        plt.subplot(311)
        plt.plot(range(0, center_padded_trace.size), center_padded_trace, 'r-',
                range(offset1, left_padded_trace.size+offset1), left_padded_trace, 'b--',
                range(0, correlation1.size), correlation1/corr_max1, 'g-',
                [corr_peak_index1], [1], 'k+')
    
        plt.subplot(312)
        plt.plot(range(0, center_padded_trace.size), center_padded_trace, 'r-',
                range(offset2, center_padded_trace.size+offset2), center_padded_trace, 'b--',
                range(0, correlation2.size), correlation2/corr_max2, 'g-',
                [corr_peak_index2], [1], 'k+')
    
        plt.subplot(313)
        plt.plot(range(0, center_padded_trace.size), center_padded_trace, 'r-',
                range(offset3, right_padded_trace.size+offset3), right_padded_trace, 'b--',
                range(0, correlation3.size), correlation3/corr_max3, 'g-',
                [corr_peak_index3], [1], 'k+')
    
        plt.show()
    
    
    x = np.arange(200)*0.01
    y1 = np.array([*map(_main, x)])
    
    y2 = np.array([*map(_main, x, np.ones(x.size,int))])
    
    plt.figure(1)
    plt.subplot(211)
    plt.title('synthetic')
    plt.plot(x,y1)
    plt.legend(('left-shifted input', 'centered input', 'right-shifted input'))
    plt.subplot(212)
    plt.title('natural')
    plt.plot(x,y2)
    plt.ylabel('x-offset of result')
    plt.xlabel('y-offset')
    plt.savefig("summary.png")
    

    这篇关于为什么在填充输入之一时python scipy互相关不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆