异步图像管道的同步

有关算子类型和同步的实用指导,请参见 Operator Types and Synchronization 教程主题。

相机同步

VisualApplets 的一个强大功能是能够组合来自不同相机源的图像。 接下来,我们将学习如何

  1. 在相机源之间进行切换
  2. 叠加两个相机的图像
  3. 多路复用相机图像
  4. 拼接两个相机的图像

在两个相机之间切换

要在两个相机之间进行切换,我们需要一个包含两个相机模块的简单设计。 在 VisualApplets 中,可以使用 operator SourceSelector(参见 'SourceSelector')在两个异步源之间进行切换。 此 operator 允许选择其输入之一,同时丢弃其他输入上的数据。 如果选择了其中一个输入,其他输入的行为将类似于连接到了 Trash operator。 可以在采集正在进行时切换输入。operator 将在新帧开始时进行切换。 两个输入的帧率和图像大小不必相同。

用于在两个相机之间切换的 VisualApplets 设计

图 208. 用于在两个相机之间切换的 VisualApplets 设计


组合两个相机源的图像数据 - 构建叠加融合

接下来,我们将了解如何组合两个相机的图像数据。 在我们的示例中,我们使用叠加融合(overlay-blend)来组合两个图像。

我们示例的规格将是:

  • 相机:两个处于基本配置模式(base configuration)的 CameraLink RGB 面阵相机
  • 分辨率:1024 x 1024 像素
  • 叠加融合(Overlay-Blend):

    公式 1. 叠加融合(Overlay Blend)


  1. 基本 Operators

    我们从设计中的基本 operators 开始,如下图所示。 我们可以使用所有默认参数和 link properties。

  2. 同步方式

    接下来,我们需要同步两个相机的的数据流。 这可以通过使用 operator SYNC 来轻松完成。 SYNC operator 控制其输入,使输出完全同步。 如您所见,我们在同步之前使用了两个缓冲区模块。 我们需要使用它们,因为我们无法确保两个相机 100% 同步。

    尽管我们同步了图像数据,但我们仍然需要注意一些限制:

    • 两个相机的帧数(即帧率)必须相同。 如果一个相机的帧率高于另一个相机,其中一个 ImageBuffer 模块将需要存储一些图像 并可能会进入溢出状态。 因此,对于长时间采集,两个相机必须使用相同的帧率采集其帧。 触发系统可以确保这一点。

    • 两个相机的 ROI 的图像大小和图像位置可能不同。 SYNC operator 将根据其参数设置,自动将较小的图像扩展到较大的图像或裁剪较大的图像。 有关更多详细信息,请参阅 SYNC operator 的说明:('SYNC')
  3. 叠加融合(Overlay-Blend)

    要做的最后一步是实现叠加融合以组合两个图像。 为了方便起见,我们为叠加融合实现使用了一个分层框(hierarchical box)。

    必须将叠加融合单独应用于所有颜色分量。 因此,我们需要将 links 拆分为所有三个颜色分量。 叠加融合再次放置在分层框中。 因此,我们在当前分层框内有三个分层框。 您可以使用复制和粘贴来复制每个颜色分量的框。

    使用 VisualApplets operators 实现上述公式有多种可能性。 通常,在实现公式之前,您应该始终尝试针对 FPGA 使用调整和优化公式。

    该公式包括与常数值的一些乘法和除法。 这些操作在 VisualApplets 中可用,但在 FPGA 上无法非常高效地实现。 如果乘法或除法可以写为 2 的幂的乘法,我们可以使用简单的位移来进行实现。 位移将完全不需要任何资源! 我们将简化

    更改为

    也就是右移 7 位,即我们丢弃七个最低有效位。

    接下来,方程式中包含一些部分,例如 255 减去 ColorA。 这是一种简单的色彩反转。白色变为暗色,暗色变为白色。 也可以通过对每个位进行简单反转来实现数值的反转。 这最终使我们能够重写方程式:

    图 2. 用于 FPGA 实现的优化叠加混合


    现在我们可以开始实现。 方程式中的其余运算可作为 VisualApplets 算子使用。 我们将需要

    • IF

    • NOT 用于反转

    • ShiftRight 用于除以 2^7

    • HWMULT 用于乘法

      除了 HWMULT 之外,VisualApplets 还包含 MULT 算子。 它们的作用相同,但 HWMULT 将使用 FPGA 中的专用乘法器,因此需要少得多的资源。

    • 为了限制位深度,我们需要一个 CastBitWidth 算子。 该算子可用于通过丢弃最高有效位(MSB)从 9 位切换到 8 位。 从公式中我们知道,不会出现大于 255 的值。

  4. 使用仿真进行验证

    1. 我们可以使用 VisualApplets 仿真轻松验证溢出混合功能。 使用两个仿真源为两个相机注入图像。 将仿真探针放置在您喜欢的任何链路上。 仿真结果将显示两个图像的叠加效果。 如果感兴趣,您还可以在分层框中检查叠加的中间结果。

    2. 无法通过仿真验证同步,因为仿真仅反映 applet 的功能部分,而不反映时序。 需要在硬件中进行验证。
  5. 添加触发

    如前所述,两个相机必须以相同的帧速率运行,以避免其中一个缓冲区溢出。 这可以通过使用触发系统轻松解决。

对两个相机的图像进行多路复用

在 VisualApplets 中多路复用图像或行非常简单。 我们将从多路复用两个相机的图像的示例开始, 即我们希望使用相同的 DMA 通道交替输出相机 A 和相机 B 的图像。

  1. 基本 Operators

    我们将需要针对两个相机的标准设计,使用两个相机模块、两个缓冲区和一个 DMA。

  2. 多路复用图像

    为了多路复用图像,我们使用 InsertImage 算子。 该算子将依次转发其输入的图像。 例如,如果我们使用两个输入,该算子将转发输入 0、1、0、1、0、1、... 的图像。 因此,处理完一个输入后,将使用下一个输入。 因此,要求两个输入处的帧数相同,即输入将具有相同的帧速率。

    如您所见,我们将图像缓冲区模块放置在插入操作之前。这是因为 InsertImage 算子本身没有缓冲区。 在转发输入 0 的图像时,输入 1 被阻塞,因此需要缓冲相机图像以避免数据丢失。

    对于每个输入(I0、I1、...),该算子提供第二个输入,称为 Ins0、Ins1、... 该输入是一个控制输入,用于控制是否应使用或丢弃图像。 因此,如果 Ins 输入处的值为 0,则可以跳过输入;如果提供值 1,则将使用该输入。 输入组 I 和 Ins 必须是同步的,即它们必须通过任意 O 型算子网络由相同的 M 型算子提供源。 有关详细信息,请参阅 'Operator Types'。由于两个输入是同步的,因此它们需要具有相同的图像尺寸。 InsertImage 将使用 Ins 输入上的第一个像素来决定是使用还是丢弃图像。 正如您在先前的屏幕截图中所看到的,我们只需使用 CONST 算子即可启用图像的使用。 将 CONST 算子的输出链路位深度设置为 1 位,并将参数“Value”设置为 1 以启用插入。

    请注意:如果其中一个 Ins 输入处的值为零,则算子仍需要处理该输入上的图像。 值零并不意味着无需提供图像。如果在某个输入处未提供图像,则算子会一直等待,直到图像可用。

    如前所述,每次只打开其中一个输入,而其他输入则被阻塞。 图像必须异步提供源,例如来自不同的缓冲区。 在下图文件中,您可以看到两个无法工作的配置。 您将不会从 applet 获得任何结果,因为它会自我阻塞。这就是所谓的“死锁”状况。

    使用 InsertImage 的死锁配置

    图 209. 使用 InsertImage 的死锁配置


    始终检查当其中一个输入处于活动状态时,另一个输入在停止时是否可以被缓冲。 不要忘记,DRC 和仿真都无法检测到死锁情况。 有关死锁的更多信息,请参阅 'Timing Synchronization'。

两个相机的拼接

在上一节中,我们对两台相机的图像进行了多路复用。图像拼接(Stitching)的处理方式几乎完全相同。 我们改用 InsertLine 算子,并通过 AppendLine 算子将两个连续的行进行追加。

InsertLine 首先会对两个输入的行进行多路复用,随后我们需要追加两行。

当然,在最后这两个示例中,也可以使用相同的图像源。 我们唯一需要注意的是,在插入之前必须拥有足够的缓冲区。 对于图像插入,我们需要缓存一整幅图像。 而对于行复制,我们只需要缓存其中一行,同时在另一条路径上处理相同的行。 若只需缓存几行,我们可以使用 ImageFifo 算子。该算子不会占用 frame grabber 的 DRAM Memory。 相反,它使用的是 FPGA 内部的 BlockRAM memory。 我们将 FIFO 配置为最多存储一行。 在下面的示例中,我们复制了一个图像行,并且该复制是反转的。 因此,我们的结果是左侧为原始图像,右侧为反转(负片)版本。

行复制

图 210:行复制