问题与前置条件
采集循环看似一直在返回有效帧,却可能在重连后泄漏缓冲区,或复用旧图像。请在实际使用的 SDK 中确认缓冲区的生命周期和设备移除事件。下方附录是与厂商无关的伪代码,不是可执行的 SDK 调用,也不构成对 Deyi 能力的声明。
准备测试
假设图像为 2000 × 1500 的 Mono8:每幅 3 MB,因此 8 个原始缓冲区在计入元数据和处理副本之前就占用 24 MB。固定设备标识,并在每次重连后定义新的采集代次(generation)。
设计工作线程循环之前,先阅读所选 SDK 中有关采集和生命周期的文档。弄清谁分配缓冲区、谁拥有采集结果、缓冲区何时归还给驱动,以及归还之后保留的引用是否仍然有效。确认文档中记载的设备移除通知,以及该通知在哪个线程上触发。如果 SDK 禁止在通知回调中阻塞,就把状态变更和关闭协调放到回调之外处理。设备标识应取自文档记载的稳定标识符,而不是枚举之后找到的第一台设备。把图像尺寸、像素格式、载荷大小、触发模式和传输配置记为验收通过的采集参数集。下文各个概念性操作名称,都不代表 Deyi 提供相应的 SDK 接口。
操作步骤
- 先配置图像尺寸和像素格式,再按 SDK 报告的载荷大小分配缓冲区。
- 采集时设置有限的超时时间;区分未收到触发、传输失败和设备被移除三种情况。
- 按文档规定的所有权规则复制或持有图像,然后再释放采集结果。
- 设备被移除时,停止工作线程,归还尚未归还的缓冲区,并丢弃旧代次的待处理结果。
- 只重连预期的那台设备,重新应用并核实配置,然后以新的代次标识符恢复运行。
VENDOR-NEUTRAL PSEUDOCODE — conceptual operations, not SDK API names
connect(expected_device_identity)
verify_configuration_and_payload()
generation = new_generation()
while connected:
result = none
owned_image = none
try:
result = acquire_with_deadline()
if result.is_valid:
owned_image = copy_or_retain_under_documented_rules(result)
process(owned_image, generation)
else:
record_acquisition_fault(result, generation)
finally:
release_owned_image_if_present(owned_image)
release_grab_result_if_present(result)
on_coordinator_receives_device_removed:
invalidate_current_generation()
stop_and_join_workers()
return_all_buffers()
discard_old_generation_results()
reconnect_expected_device_and_verify_configuration()
generation = new_generation()采集时设定有限的超时时间,并在访问图像数据之前先检查采集结果。超时可能只是外部触发没有到来;传输故障或设备被移除则需要走另一条恢复路径。把每个有效帧交给处理环节之前,先将它与采集代次以及帧或事件标识关联起来。可以复制到应用自己管理的存储,也可以按 SDK 文档规定的规则保留所有权。无论哪种做法,处理过程抛出异常时和正常完成时一样,都要释放资源。为处理队列设定上限,并明确队列满了之后怎么办。内存悄悄越涨越大,不能算作有效的背压策略;拿最近一帧去充当新请求的图像,也不能替代缺失的图像。
测试记录示例
以下为示例性假设,并非 Deyi 的实测性能。请将这些数值替换为你自己经签字确认的测试记录。
| 记录项 | 假设值 |
|---|---|
| 队列容量 | 8 |
| 未压缩图像数据量 | 3 MB |
| 存储容量 | 24 MB |
| 样本数 | 1000 |
在保持已配置采集速率的同时,人为让消费端变慢。记录采集代次、帧标识符、队列深度、存活缓冲区数量和超时原因。如果图像被复制,24 MB 的计算结果不包含这些副本;如果保留的是引用,SDK 必须允许这些引用在相应的时间内保持有效。finally 块同样示范了处理过程抛出异常时的释放。重连之后,注入一个延迟到达的旧代次结果,确认它不会变成当前的检测结果。
设备被移除时,停止接收受影响代次的新任务,并先协调好工作线程的终止,再释放它们可能仍在访问的资源。按 SDK 的约定取消或完成尚未完成的操作,归还缓冲区,并丢弃未被消费的旧代次结果。重连预期的设备,并核实已验收的配置,不要想当然地认为默认值与上一次会话一致。分配新缓冲区之前,先回读载荷信息。新会话准备就绪之后,才创建新的代次。来自旧会话的迟到回调或排队中的结果,即使帧号与当前帧相似,也必须被代次检查拒绝。示例中的原始缓冲区算式只是内存消耗的一个组成部分;应把副本、队列和算法工作空间也纳入按实测得出的预算。
流程的两种视图
稳定的相机采集:缓冲区、超时与重连 — 1
所有权从采集环节转到处理环节,只有在消费端不再需要这些数据之后才归还。
- 采集
- 持有或复制
- 处理
- 释放
稳定的相机采集:缓冲区、超时与重连 — 2
超时、移除和有序关闭需要不同的状态转换;重连必须开启一个干净的新采集代次。
- 超时
- 移除
- 关闭
故障排查
- 内存持续增长,说明存在未释放的采集结果,或消费端队列没有上限。
- 图像损坏,提示缓冲区归还给驱动之后仍被使用。
- 重连后反复出现旧图像时,需要检查队列和代次标识符,而不能只是重新打开设备。
验收与交接
运行示例中的 1000 帧试验,并加上设备移除、恢复和关闭这几种情况。确认内存有界、没有跨代次的结果,并且以明确的故障代替被复用的图像。再用慢速消费端重复一遍;原始缓冲区的算式并不是总内存预算。
测试前先设定验收限值,并保留原始证据。此处的示例并不能说明所供型号具备相应能力。
验收要把持续采集、人为中断和慢速消费端场景结合起来。对每个计划内的请求,都记录存活缓冲区、队列深度、进程内存、代次转换和终止原因。按受控流程移除并恢复设备,然后在采集尚未完成时停止应用程序。确认关闭流程能够完成,没有任何工作线程访问已释放的内存,也没有旧图像变成新的检测结果。测试处理过程中的异常,以走通 finally 路径。放行前,把最终的设备标识和配置与验收记录比对。示例中的 1000 帧运行只提供功能覆盖,不能保证长期无泄漏或长期可靠。交接材料应包含实际使用的 SDK 版本、所有权决定、队列策略、重连顺序和故障证据,其中可执行的厂商专用代码要对照其自身文档审查。
来源与技术参考资料
这些资料说明了本教程所用方法的依据与适用范围。文中的检查示例仅供参考;量产验收需要用你自己的样品取得证据。
- Programming with pylon CBasler核查于
- pylon .NET SamplesBasler核查于
部件与选型参考
- 智能相机与基于 PC 的视觉系统
- GigE 与 USB3 工业相机
- 机器视觉系统
- machine vision software · 英文参考资料
- EAN-13 追溯:产线验收
- EAN-13 追溯:解码与数据规则
- 验收并集成可见液位工作流
- 面向可见液位替代指标的 AI 辅助工作流
- 关联检测记录、图像与工件标识符
- OCR 标签核对:验收与 PLC 约定
- OCR 标签核对:原生工作流与精确匹配
- 未封口包装完整性检测的验收与集成
- 搭建 AI 辅助的未封口包装完整性工作流
- 用明确的状态构建 PLC 与视觉系统的握手
- 密封与胶条外观:产线验收
- 密封与胶条外观:工作流规则
- SKU 颜色分选:验收与未知物品分流
- SKU 颜色分选:类型明确的颜色与 SKU 规则
- 表面缺陷检测:验收与产线输出
- 表面缺陷检测:限定范围的 AI 评估
- 触发到 PLC 判定的延迟负载测试
- 完整视觉配方的版本管理与回滚

