找到numpy数组之间最低差异的位置

时间:2015-07-19 10:17:37

标签: python numpy

我有两个音乐文件:一个是无损的,声音间隙很小(此时它只是沉默,但它可能是任何东西:正弦曲线或只是一些噪音)在开头和一个mp3:

In [1]: plt.plot(y[:100000])
Out[1]: 

Lossless file

In [2]: plt.plot(y2[:100000])
Out[2]: 

mp3 file

这个列表相似但不完全相同所以我需要缩小这个差距,找到第一个出现在另一个列表中的最低delta错误。

这是我的解决方案(5.7065秒):

error = []
for i in range(25000):
    y_n = y[i:100000]
    y2_n = y2[:100000-i]
    error.append(abs(y_n - y2_n).mean())
start = np.array(error).argmin()

print(start, error[start]) #23057 0.0100046

有没有任何pythonic方法来解决这个问题?

修改 在计算特殊点之间的平均距离(例如数据== 0.5)之后,我将搜索范围从25000减少到2000.这给了我合理的0.3871s时间:

a = np.where(y[:100000].round(1) == 0.5)[0]
b = np.where(y2[:100000].round(1) == 0.5)[0]

mean = int((a - b[:len(a)]).mean())
delta = 1000

error = []
for i in range(mean - delta, mean + delta):
...

3 个答案:

答案 0 :(得分:3)

你要做的是这两个信号的cross-correlation

可以使用scipy库中的signal.correlate轻松完成此操作:

import scipy.signal
import numpy as np

# limit your signal length to speed things up
lim = 25000

# do the actual correlation
corr = scipy.signal.correlate(y[:lim], y2[:lim], mode='full')

# The offset is the maximum of your correlation array,
# itself being offset by (lim - 1):
offset = np.argmax(corr) - (lim - 1)

您可能需要查看类似问题的this答案。

答案 1 :(得分:1)

让我们先生成一些数据

N = 1000
y1 = np.random.randn(N)
y2 = y1 + np.random.randn(N) * 0.05
y2[0:int(N / 10)] = 0

在这些数据中,y1y2 几乎相同(请注意小的附加噪音),但y2的前10%为空(与你的例子类似)

我们现在可以计算两个向量之间的绝对差值,找到绝对差值低于灵敏度阈值的第一个元素:

abs_delta = np.abs(y1 - y2)
THRESHOLD = 1e-2
sel = abs_delta < THRESHOLD
ix_start = np.where(sel)[0][0]


fig, axes = plt.subplots(3, 1)
ax = axes[0]
ax.plot(y1, '-')
ax.set_title('y1')
ax.axvline(ix_start, color='red')
ax = axes[1]
ax.plot(y2, '-')
ax.axvline(ix_start, color='red')
ax.set_title('y2')

ax = axes[2]
ax.plot(abs_delta)
ax.axvline(ix_start, color='red')
ax.set_title('abs diff')

sample data plotted

如果重叠部分确实“几乎相同”,则此方法有效。如果相似度较低,您将不得不考虑更智能的对齐方式。

答案 2 :(得分:0)

我认为你要找的是相关性。这是一个小例子。

import numpy as np

equal_part = [0, 1, 2, 3, -2, -4, 5, 0]
y1 = equal_part + [0, 1, 2, 3, -2, -4, 5, 0]
y2 = [1, 2, 4, -3, -2, -1, 3, 2]+y1

np.argmax(np.correlate(y1, y2, 'same'))

输出:

7

因此,这将返回时间差,其中两个信号之间的相关性达到最大值。如您所见,在示例中,时差应为8,但这取决于您的数据...... 另请注意,两个信号的长度相同。