我有两个音乐文件:一个是无损的,声音间隙很小(此时它只是沉默,但它可能是任何东西:正弦曲线或只是一些噪音)在开头和一个mp3:
In [1]: plt.plot(y[:100000])
Out[1]:
In [2]: plt.plot(y2[:100000])
Out[2]:
这个列表相似但不完全相同所以我需要缩小这个差距,找到第一个出现在另一个列表中的最低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):
...
答案 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
在这些数据中,y1
和y2
几乎相同(请注意小的附加噪音),但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')
如果重叠部分确实“几乎相同”,则此方法有效。如果相似度较低,您将不得不考虑更智能的对齐方式。
答案 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,但这取决于您的数据...... 另请注意,两个信号的长度相同。