本篇博客技术内容可以应用于 FLIR 的网口和USB3的相机

Flir Blackfly S USB3 产品介绍

Blackfly S 采用业内先进的冰块外形传感器。
具有强大功能,可以轻松生成所需的精确图像,并加速应用程序开发。
包括对图像捕获和相机预处理的自动和精确手动控制。
Blackfly S 提供GigE、USB3、套装和板级版本。
精确图像 索尼CMOS传感器中的选择包括:全局快门、偏振和高灵敏度BSI传感器。

下面主要讲解缓冲区和缓冲区处理模式的本质及其工作方式,并提供拍摄图像的预期效果示例

相机缓冲区介绍

图像被摄像头拍摄后,会自动传输到 PC 并存储在 RAM 中。
内存中为存储图像分配的空间称为缓冲区。
缓冲区数量根据摄像头最大帧率,内存默认自动分配。
摄像头相关的缓冲区数量可以通过将流缓冲区计数模式从自动切换为手动并同时为手动流缓冲区计数分配一个值来更改。
缓冲区最大数量取决于 RAM 的可用内存,每个缓冲区的大小则取决于图像尺寸。

Spinnaker 1.13 及更高版本拥有自动缓冲计数模式功能。 之前版本默认将缓冲区数量设置为 10。

在使用图像的时候,只能在图像从缓冲区检索出来后与图像进行交互。 这类交互包括将图像显示在屏幕上、保存到磁盘或应用图像处理。

缓冲区处理

缓冲区处理决定每个摄像头可用的缓冲区数(如果可以覆盖)以及检索图像的顺序

缓冲区处理模式

Spinnaker 中有四类缓冲区处理:

1、先处理最新的:
应用处理输出缓冲区队列末尾图像(最新可用的那一个)
此方式对于运动预测这类需要始终获取最新的帧但之前的帧也可以增加有价值信息的应用比较好。
在这里插入图片描述
2、仅处理最新的:
应用始终处理最近完成的图像(最新的那一个)。 丢弃之前的图像。 流缓冲区计数被忽略。 该模式通常用在实时显示 GUI,其中要求摄像头和显示屏之间没有延迟。
在这里插入图片描述
3、先处理最早的:
应用始终处理输出缓冲区队列首个图像(最早可用的那一个)
在这里插入图片描述
4、先盖写最早的:
应用始终处理输出缓冲区队列首个图像(最早可用的)。 如果有新图像传入,它会从队列开头盖写缓冲区。 看上去像一个循环缓冲区。
在这里插入图片描述

缓冲区处理模式示例

上面的解释还是比较抽象,下面举几个例子就清楚了

示例 1

触发摄像头 6 次。 每次触发后,我们将检索图像,然后输出 FrameID(Frame ID 始终从 0 开始)。
示例条件:

  • 1 FPS
  • 无图像处理
  • 缓冲区数量或缓冲区处理模式无变化
    示例结果:
  • 0、1、2、3、4、5
    无论使用哪种缓冲区处理模式,结果应当都一样。 但是,如果摄像头触发比主机的处理能力更快,或者说如果主机端有延迟,那么图像将被丢弃。 这样的话,输出的帧 ID 可能与上文显示的结果不匹配 同样,图像检索位置与其传输位置不一样的时候,缓冲区处理模式将决定检索的图像以及图像的顺序。

示例 2

触发摄像头 6 次。 第六次触发后,我们开始检索三个图像,然后输出 FrameID。

示例条件:

  • 1 FPS
  • 无图像处理
  • 设置缓冲区数量为 3(PC 只在内存保留 3 张图像)
  • 逐个应用每种缓冲区处理模式

先处理最新的:

  • 2、1、0
  • 没有盖写,摄像头保留了先拍摄的三张图像,丢弃 3、4、5 帧
  • 仅处理最新的:
  • 5、错误
  • 摄像头保留了最新的图像,但尝试检索不存在的图像时,出现了错误
  • 先处理最早的:
  • 和“先处理最新的”一样,区别是最早图像先被检索
  • 先盖写最早的:
  • 3、4、5
  • 帧 0、1 和 2 被盖写了,表示帧 3 是最早的图像且率先被检索,然后再检索帧 4 和 5

传输队列(摄像头机载图像缓冲区)

每个摄像头都有一个机载图像缓冲区,每个拍摄的图像都要经过该缓冲区。 只要摄像头保持通电,它也可以用来无限期存储图像。 该图像缓冲区可以存储多张图像。

Blackfly S 摄像头拥有 240 MB 的图像缓冲区。

每个图像占用的空间大小是摄像头最大分辨率的四倍。 例如,BFS-U3-13Y3C 摄像头的分辨率是 1.3 MP,那么每张图像就要占用图像缓冲区 5.2 MB 的空间。 可以存储的最大图像数量见 TransferQueueMaxBlockCount 节点。 当前在摄像头上缓冲的图像数量见 TransferQueueCurrentBlockCount 节点。

如果 USB3 摄像头拍摄图像后 PC 上没有可用的缓冲区,则该图像将被自动存储在机载缓冲区中。 一旦 PC 有可用空间,摄像头机载缓冲区中的图像将自动传送到 PC。 如果使用的是“先处理最新的”模式,此情况会干扰预期的图像顺序。

通过Code更改缓冲区大小

通过Spinnaker C++ 接口 将缓冲区大小更改为11,默认为10

Spinnaker::GenApi::INodeMap & sNodeMap = cam->GetTLStreamNodeMap();
CIntegerPtr StreamNode = sNodeMap.GetNode(“StreamDefaultBufferCount”);
INT64 bufferCount = StreamNode->GetValue();
StreamNode->SetValue(11);

通过 GetTLStreamNodeMap 获得NodeMap
通过 GetNode 获得Node
通过 GetValue 默认缓冲区大小
通过 SetValue 将缓冲区大小设置为11