如何更好地同步来自 LED 和 TTL 脉冲的信号?

信息处理 Python 相关性 下采样 重采样 同步
2022-01-28 16:05:03

我想使用 Python 同步我的视频和电压数据。(我使用 Bonsai 和 Open Ephys 获得了这些数据,用于开放野外勘探实验。)

我发了150 ms向记录电压数据的计算机发送长 TTL 脉冲,同时发送到相机视野中的 LED 以将其打开。我以 20-60 秒的间隔随机发送脉冲。我想将 LED 脉冲与 TTL 对齐以同步我的数据集。

两个记录不一定同时开始和结束,因此其中一个数据集的脉冲可能比另一个数据集少。

电压数据记录在30000 Hz采样率,视频大约30 Hz.

我尝试对电压数据进行下采样,将两个数组关联起来并找到最大相关性来计算滞后,然后将视频数据移动偏移量。

我的第一个问题是对电压数据进行下采样。我从平均步长计算了实际的采样率,发现相机大约是30.08207 Hz.

我尝试使用resampy 的 resample

resampy.resample(voltage_data, voltage_data_sampling_rate, video_sampling_rate)

其中电压数据采样率是30000 Hz和 video_sampling_rate30.08207 Hz. 这将返回一个与原始电压数组大小相同的数组。

1. 我怎样才能得到一个与我的视频具有相同采样率的信号?

为了在不使用它的情况下重新采样我的数据,我生成了一个采样率倍数的数组(3000030.082074=997.271)),将这些转换为整数并获取这些索引。我知道这是非常基本的,但我认为它可以让我检查我是否可以编写此代码的其余部分。

我使用以下方法计算了相关性numpy.correlate

correlation = np.correlate(video, voltage, "full")

我根据标准差和中位数设置了一个阈值,并将所有值替换为0s低于阈值以消除噪声。

我检查了哪个数组更短并用0s.

short_array = np.pad(short_array, (0, len(long_array)-len(short_array)), 'constant')

我根据最大相关性计算了两个信号之间的滞后:

lag = (np.argmax(corr) - (corr.size + 1)/2)/avg_sampling_rate_video

这个结果是对的。它将我的 2-5 秒延迟减少到大约100 ms.

plt.plot(downsampled_voltage_time, downsampled_voltage_TTL)
plt.plot(video_time, video_sync_pulses)

示例同步峰值 在此处输入图像描述

我需要这个比那个更好,我希望滞后接近30 ms.

2.是下采样导致了这个问题,还是这种方法有其他问题?

2个回答

您可能在这里缺少的是网络摄像头的帧速率可能无处不在,特别是如果您通过获取成像设备的句柄然后使用计时器请求帧来捕获视频。

无论如何,无论您在哪里捕获帧,也要捕获其时间戳。这将允许您更好地交叉参考具有电压时间序列的帧。

您必须做的第一件事是至少同步第一个脉冲。因此,无论您将在后续处理步骤中做什么,前两个脉冲(一个来自电压时间序列,一个来自视频时间序列)必须同步。为此,您只需移动一个(或另一个)时间序列,以使脉冲的上升沿重合。

现在,从两个时间序列中提取以秒为单位的相同数量的波形。因此,例如从每个中提取 5 秒。一个将是 150 个样本长,其他 150000 个样本长。始终对更详细的进行二次抽样。

这两个波形现在将与您的设备允许的一样同步。如果您将它们并排绘制,您可能会发现一些不匹配,因为您的相机的帧速率有一些抖动。

避免这种情况的唯一方法是通过降低电压时间序列样本来“抵消”FPS 抖动,以便电压时间序列(具有更高的分辨率)“赶上”(或者实际上是滞后)视频。

您可以通过匹配每个单独脉冲的宽度或通过动态时间规整 (DTW)来做到这一点。

第一种方法很简单:从两个波形中提取一个脉冲周期,测量脉冲宽度(在任何一个波形中都必须为 150 毫秒,视频波形中为 4.5 帧,电压波形中为 4500 个样本),将电压波形下采样一个因子等于脉冲宽度之间的比率,移动到下一个脉冲周期。

第二种方法基本上做同样的事情,甚至可以返回一个正是这个“时间提前”信号的信号,你必须通过它转换一个波形,以便它赶上另一个。在这种情况下,事情就更简单了:将电压下采样到视频采样频率,这将为您提供近似匹配。然后,使用相同采样频率的两个波形,将它们运行通过 DTW 并应用转换。

希望这可以帮助。

我按照问题中的描述关联了两个数据集,然后对它们进行了修剪以确保第一个脉冲在另一个数据集中具有相应的脉冲。然后我能够检测到两者的上升沿并移动其中一个。

这样我就有大约 30 毫秒的精度。