跳转到内容

Synchronous Free Run (blaze)#

Synchronous Free Run 功能使您可以同时操作多台 blaze 相机(即使它们不在同一网络中),而它们的光源不会相互干扰。

该功能的使用#

为什么使用 Synchronous Free Run#

如果要使用多台 blaze 相机拍摄同一场景,您必须错开各台相机的曝光,以免它们的光源相互干扰。与环境光一样,各台相机的光源也会导致图像质量下降。

使用 PTP,您可以让一组相机以同步自由运行的方式捕获图像,但是曝光以精确的时间间隔和时间顺序连续开始。这样,一台相机的光源不会干扰其他相机的测量。

运作原理#

有两种配置 Synchronous Free Run 的方法。为了帮助您确定最适合您的选择,在涉及图像采集时,您必须了解 blaze 相机的一般工作原理。

采集图像时,每个帧由八个子帧组成(如果 Fast Mode 已启用,则为 4 个子帧)。可以将每个子帧视为单独的曝光,因为在暴露每个子帧后,照明将关闭并且传感器将重置。

帧曝光阶段#

曝光期间分为以下几个阶段:

  • Startup: 这发生在第一个和第五个子帧之前。
  • 重置:传感器重置。在采集每个子帧时重置。
  • 曝光:快门打开,传感器曝光。针对每帧。
  • 读出:从传感器中读取子帧期间收集的数据。

相机仅在曝光阶段发光。

下图显示了帧曝光的不同阶段(仅显示了子帧 1、2 和 8)。

帧曝光阶段

Synchronous Free Run#

在自由运行模式下操作相机意味着相机使用内部周期性触发定时器来触发自身。

在同步自由运行模式下,相机时钟使用 PTP 进行同步。同步时钟也会促使内部触发定时器同步。

将相机设置为同步自由运行时,可以通过为相机指定单独的采集开始时间来调整相机的采集。一旦达到相机的采集开始时间,内部触发定时器就会启动,相机以固定的帧速率采集数据。

信息

可以设置过去的开始时间。这种情况被视为过去已启动内部计时器。

信息

在发出 AcquisitionStart 命令之前,相机不会开始采集。

有两种使用 Synchronous Free Run 的方法:

交错模式#

如果要同时操作两个 blaze 相机,请选择 interleaved 模式。在这种模式下,一个相机会发光,而另一个相机会执行传感器读出。

交错式 Synchronous Free Run

信息

相机的传感器时序必须完全相同,即您必须为 ExposureTimeFastModeHDRMode 参数设置相同的值。

传感器时序也由传感器读出时间决定,因为这是传感器的属性,所以不能更改。但是,传感器读出时间可能会因相机的硬件版本而异。如果是这种情况,请改用 consecutive 模式。

连续模式#

在大多数情况下,以交错模式操作两个以上的相机是不切实际的。由于网络数据包的紧密连续性,您很可能会遇到网络数据包丢失的情况,因此无法完全采集数据。为了获得更好的效果,请使用连续模式,在这种模式下,相机一个接一个地连续采集帧。

如果您想同时操作具有不同传感器时序的多个相机,也必须使用此模式。

连续式 Synchronous Free Run

如果要最大限度地提高可实现的帧速率,则可以将相机的采集开始时间设置为前一个相机的读出阶段的时间。

配置相机#

信息

pylon blaze 补充软件包含有 MultiCamHelper C++ 库。此库是 C++ 示例集合的一部分,位于 MultiCam/MultiCamHelper 文件夹中。

该库提供了 BlazeSynchronousFreeRunHelper 类,Basler 建议使用该类设置多个 blaze 相机以实现同步自由运行、捕获数据以及按时间顺序匹配属于一起的帧。SynchronousFreeRun C++ 示例中显示了如何使用这个类。

MultiCamHelper 库还提供了 GenericSynchronousFreeRunHelper 类,如果您想同步 blaze 和 2D GigE 相机,这个类很有用。Multicam/ColorAndDepth 文件夹中的示例演示了如何使用这个类。

如果您使用 C++ 以外的编程语言,或者您不想使用 MultiCamHelper 库提供的类,本节将介绍配置相机以实现同步自由运行的过程。此过程可用于配置交错和连续模式。

使用的变量#
  • t_startup[i]:第 i 个相机的帧启动持续时间。
  • t_reset[i]:第 i 个相机的重置持续时间(在每个子帧的开头进行重置)。
  • t_exp[i]:第 i 个相机对单个子帧的曝光持续时间。
  • t_read[i]:第 i 个相机对单个子帧的读出持续时间。
  • t_frame[i]:第 i 个相机获取一帧的所有子帧所需的总时间。

可以从相机中检索出实际值。下表列出了必须读出的参数名称:

变量 相机参数
t_startup StartupTime
t_reset ResetTime
t_exp ExposureTime
t_read ReadoutTime
t_frame FrameDuration

上面列出的所有相机参数返回的值均以微秒 (µs) 为单位。

要配置相机并开始同步自由运行:

  1. 在每个相机上,启用 PTP 等待,直到执行了主时钟选择并且时钟充分同步。
    有关详细信息,请参阅 Precision Time Protocol (blaze)

  2. 在每个相机上,为 ExposureTimeFastModeHDRMode 配置所需的设置。

    信息

    为交错同步自由运行模式设置相机时,您必须为 ExposureTimeFastModeHDRMode 设置相同的值。

  3. 下文所述计算最大可能帧速率 fps_max

  4. 在每个相机上,将 AcquisitionFrameRateEnable 参数设置为 true,通过将 AcquisitionFrameRate 参数设置为等于或小于 fps_max 的值来指定所需的帧速率。

    信息

    您必须在所有相机上指定相同的帧速率。

  5. 对于每个相机,计算所需的触发偏移并按照下文所述设置生成的采集开始时间。

  6. 准备应用程序的采集循环。

  7. 在每台相机上,发出 StartAcquisition 命令。

  8. 采集每台相机的图像。

确定最大帧速率#

当使用连续式 Synchronous Free Run 时,每台相机的最大帧速率受相机数量和每台相机的帧时长限制。

使用交错同步自由运行时,相机能以最大的可能帧速率运行。

在下文中,fps_max[i] 表示第 i 个相机的 AcquisitionFrameRate 参数的最大允许值。要使用 pylon SDK 的 API 读取相机 ifps_max[i],您可以使用以下代码片段:

C++

auto max = camera[i].AcquisitionFrameRate.GetMax();

C#

var max = camera[i].Parameters[PLBlaze.AcquisitionFrameRate].GetMaximum();

交错模式#

由于在交错模式下,所有相机的传感器时序必须相同,请将 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)

计算触发偏移和设置采集开始时间#

各个采集开始时间必须交错的时间量取决于传感器时序,以及使用的是交错还是连续同步自由运行模式。

采集开始时间 t_acq_start[i] 应设置成未来的某个时间点,以确保在应用程序配置所有相机并设置采集循环之前,没有相机开始采集。配置一个相机需要大约 400 ms。

以下伪代码片段说明了如何计算相机的触发偏移以及如何设置采集开始时间。

所用变量的含义:

  • n:相机数量。
  • camera[]:相机数组。
  • t_0:当前 PTP Timestamp [ns]。
  • fps_max:最大的可能帧速率 [Hz]。
  • trigger_offset:与前一个相机相比,相机的触发器延迟的时间量。
  • t_acq_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