Synchronous Free Run (blaze)#
该功能的使用#
为什么使用 Synchronous Free Run#
如果要使用多台 blaze 相机拍摄同一场景,您必须错开各台相机的曝光,以免它们的光源相互干扰。与环境光一样,各台相机的光源也会导致图像质量下降。
使用 PTP,您可以让一组相机以同步自由运行的方式捕获图像,但是曝光以精确的时间间隔和时间顺序连续开始。这样,一台相机的光源不会干扰其他相机的测量。
运作原理#
有两种配置 Synchronous Free Run 的方法。为了帮助您确定最适合您的选择,在涉及图像采集时,您必须了解 blaze 相机的一般工作原理。
采集图像时,每个帧由八个子帧组成(如果 Fast Mode 已启用,则为 4 个子帧)。可以将每个子帧视为单独的曝光,因为在暴露每个子帧后,照明将关闭并且传感器将重置。
帧曝光阶段#
曝光期间分为以下几个阶段:
- Startup: 这发生在第一个和第五个子帧之前。
- 重置:传感器重置。在采集每个子帧时重置。
- 曝光:快门打开,传感器曝光。针对每帧。
- 读出:从传感器中读取子帧期间收集的数据。
相机仅在曝光阶段发光。
下图显示了帧曝光的不同阶段(仅显示了子帧 1、2 和 8)。
Synchronous Free Run#
在自由运行模式下操作相机意味着相机使用内部周期性触发定时器来触发自身。
在同步自由运行模式下,相机时钟使用 PTP 进行同步。同步时钟也会促使内部触发定时器同步。
当将相机设置为 Synchronous Free Run 时,可以通过为各相机指定单独的 Acquisition Start 时间来对齐相机的采集。一旦达到相机的 Acquisition Start 时间(由 SyncFreeRunTimerStartTimeHigh 和 SyncFreeRunTimerStartTimeLow 参数指定),内部的 trigger timer 就会启动,并且相机以固定的帧率采集数据。
信息
可以设置过去的开始时间。这种情况被视为过去已启动内部计时器。
信息
在发出 AcquisitionStart 命令之前,相机不会开始采集。
同步 blaze 和 ace / ace 2 相机
- 如果您的应用设置包含 ace camera,则开始时间必须在不久的将来。
- 如果您的应用设置包含 ace 2 camera,则 blaze 相机的开始时间必须为 0。
有两种使用 Synchronous Free Run 的方法:
交错模式#
如果要同时操作两个 blaze 相机,请选择 interleaved 模式。在这种模式下,一个相机会发光,而另一个相机会执行传感器读出。
信息
相机的传感器时序必须完全相同,即您必须为以下项设置相同的值: ExposureTime, FastMode和 HDRMode Property。
传感器时序也由传感器读出时间决定,因为这是传感器的属性,所以不能更改。但是,传感器读出时间可能会因相机的硬件版本而异。如果是这种情况,请改用 consecutive 模式。
连续模式#
在大多数情况下,以交错模式操作两个以上的相机是不切实际的。由于网络数据包的紧密连续性,您很可能会遇到网络数据包丢失的情况,因此无法完全采集数据。为了获得更好的效果,请使用连续模式,在这种模式下,相机一个接一个地连续采集帧。
如果您想同时操作具有不同传感器时序的多个相机,也必须使用此模式。
如果要最大限度地提高可实现的帧速率,则可以将相机的采集开始时间设置为前一个相机的读出阶段的时间。
配置相机#
信息
pylon blaze 补充软件包含有 MultiCamHelper C++ 库。此库是 C++ 示例集合的一部分,位于 MultiCam/MultiCamHelper 文件夹中。
该库提供了 BlazeSynchronousFreeRunHelper 类,Basler 建议使用该类来设置多个 blaze 相机以实现 Synchronous Free Run、捕获数据并匹配按时间顺序属于同一帧的帧。如何使用此类展示在 SynchronousFreeRun C++ 示例中。
MultiCamHelper 库还提供了 GenericSynchronousFreeRunHelper 类,如果您想同步 blaze 和 2D GigE 相机,这个类很有用。Multicam/ColorAndDepth 文件夹中的示例演示了如何使用这个类。
如果您使用 C++ 以外的编程语言,或者您不想使用 MultiCamHelper 库提供的类,本节将介绍配置相机以实现同步自由运行的过程。此过程可用于配置交错和连续模式。
使用的变量#
t_startup[i]:第 i 个相机的帧启动时间持续时间。t_reset[i]:第 i 个相机的复位时间持续时间(复位发生在每个子帧的开始)。t_exp[i]:单个子帧的第 i 个相机 Exposure Time 持续时间。t_read[i]:单个子帧的第 i 个相机读出时间持续时间。t_frame[i]:第 i 个相机采集一帧的所有子帧所需的总时间。
可以从相机中检索出实际值。下表列出了必须读出的参数名称:
| 变量 | 相机参数 |
|---|---|
t_startup | StartupTime |
t_reset | ResetTime |
t_exp | ExposureTime |
t_read | ReadoutTime |
t_frame | FrameDuration |
上面列出的所有相机参数返回的值均以微秒 (µs) 为单位。
要配置相机并开始同步自由运行:
-
在每个相机上,启用 PTP 等待,直到执行了主时钟选择并且时钟充分同步。
有关详细信息,请参阅 Precision Time Protocol (blaze)。 -
在每台相机上,配置所需的设置:
ExposureTime,FastMode和HDRMode.信息
当将相机设置为交错式 Synchronous Free Run 模式时,您必须为以下项设置相同的值:
ExposureTime,FastMode和HDRMode. -
计算最大可能帧率
fps_max如所述 图表. -
在每台相机上,设置
AcquisitionFrameRateEnable参数至true通过将AcquisitionFrameRate参数设置为小于或等于以下值的值来指定所需的帧率:fps_max.信息
您必须在所有相机上指定相同的帧速率。
-
对于每个相机,计算所需的触发偏移并按照下文所述设置生成的采集开始时间。
-
准备应用程序的采集循环。
-
在每台相机上,发出
StartAcquisition命令。 -
采集每台相机的图像。
确定最大帧速率#
当使用连续式 Synchronous Free Run 时,每台相机的最大帧速率受相机数量和每台相机的帧时长限制。
使用交错同步自由运行时,相机能以最大的可能帧速率运行。
在下文中, fps_max[i] 表示第 i 台相机的最大允许值 AcquisitionFrameRate 参数。要读取 fps_max[i] 小节了解 相机 i 使用 pylon SDK 的 API,您可以使用以下代码片段:
C++
C#
交错模式#
由于在交错模式下,所有相机的传感器时序必须完全相同,请将 fps_max 设置为任一相机的最大帧率值。
连续模式#
您可以计算最大帧率 fps_max 在连续模式下,如以下伪代码片段所示:
fmax_min = min(fps_max[0], ... ,fps_max[n-1])
t_total = 0
for i = 0 to n-1
t_total = t_total + t_frame[i] - t_startup[i] - t_reset[i] - t_read[i]
endif
t_total = t_total + t_startup[0] + t_reset[0]
fps = 1e6 / t_total
fps_max = min(fps, fmax_min)
计算触发偏移和设置采集开始时间#
各个采集开始时间必须交错的时间量取决于传感器时序,以及使用的是交错还是连续同步自由运行模式。
Acquisition Start 时间 t_acq_start[i] 应设置为未来的某个时间点,以确保在您的应用程序配置完所有相机并设置好采集循环之前,没有任何相机开始采集。配置一台相机大约需要考虑 400 毫秒的时间。
以下伪代码片段说明了如何计算相机的触发偏移以及如何设置采集开始时间。
所用变量的含义:
n:相机数量。camera[]:相机数组。t_0:当前 PTP Timestamp [ns]。如果仅连接了相机,则 Timestamp 计算自的主设备上电以来的时钟周期数。这意味着时间标尺是随意的、相对的,且仅在此网络中有效。若要获得绝对时间标尺,请连接同步到协调世界时(例如 TAI 或 UTC)的设备。fps_max:最大可能帧率 [Hz]。trigger_offset:与前一台相机相比,相机的触发延迟时间量。t_acq_start[]:Acquisition Start 时间 [ns]。t_safety:为补偿抖动而应增加的采集延迟时间 [µs]。推荐值:250 µs。
camera[0].TimestampLatch.Execute()
t_0 = camera[0].TimestampLatchValue.GetValue()
t_acq_start[0] = t_0 + n * 400 * 1000000
for i = 0 to n-1
camera[i].SyncFreeRunTimerStartTimeLow.SetValue(t_acq_start[i] & 0xffffffff)
camera[i].SyncFreeRunTimerStartTimeHigh.SetValue(t_acq_start[i] >> 32)
camera[i].SyncFreeRunTimerUpdate.Execute()
camera[i].SyncFreeRunEnable.SetValue(true)
if i < n-1
if interleaved_mode
trigger_offset = 1000 * (t_safety + t_exp[i])
else
trigger_offset =
1000 * (t_safety + t_frame[i] - t_read[i] - t_startup[i+1] - t_reset[i+1]
endif
t_acq_start[i+1] = t_acq_start[i] + trigger_offset
endif
endfor