当前位置: 首页 > news >正文

【C#】以 BlockingCollection 为核心的多相机 YOLO 检测任务处理框架 - 指南

以 BlockingCollection 为核心的多相机 YOLO 检测任务处理框架

在工业视觉应用中,我们经常会遇到一台电脑同时接入多台相机的场景。比如 10 台相机同时拍摄生产线上的产品,通过硬件 IO 触发采图,然后进行 YOLO 缺陷检测。

如果不合理设计,容易出现以下挑战:

  • 回调线程阻塞导致相机触发丢帧
  • 多线程抢占 YOLO 对象导致检测结果错乱
  • 图像内存泄露或 UI 更新异常

本文将以 BlockingCollection 为核心,介绍一个线程安全、支持多相机任务队列的 YOLO 检测框架。


1. 为什么选择 BlockingCollection

BlockingCollection<T> 是 .NET 提供的一个 线程安全的生产者-消费者队列,非常适合处理相机采图任务。

优点:

  • 线程安全:多个线程同时 Add/Take 没问题
  • 阻塞消费:队列为空时,Take 或 GetConsumingEnumerable 会自动等待
  • 容量限制:防止队列无限增长
  • 优雅结束:调用 CompleteAdding() 后,消费者循环可以自动退出

Tip:BlockingCollection 内部默认基于 ConcurrentQueue<T>,也可以替换为 ConcurrentStack<T>ConcurrentBag<T>


2. 相比 ConcurrentQueue / ConcurrentBag 的优势

特性ConcurrentQueueConcurrentBagBlockingCollection
顺序FIFO无序FIFO / 自定义
阻塞
容量限制
支持生产者-消费者模式✅ 内置
可结束队列/循环✅ CompleteAdding

总结在 ConcurrentQueue/Bag 基础上加了阻塞、容量、结束控制,更适合多线程任务队列场景。就是:BlockingCollection 本质上


3. 多相机任务处理思路

针对 10 台相机 IO 触发的场景,设计思路如下:

  1. Update 回调

    • 回调线程只做一件事:将 CameraInfo 入队
    • 避免在回调中执行耗时的检测任务,防止阻塞触发
  2. 后台 WorkerLoop

    • BlockingCollection 队列中取任务
    • 调用 Detection() 进行 YOLO 处理
  3. Detection 处理逻辑

    • 图像预处理(Blob、裁剪、摆正等)
    • YOLO 推理(检测或分割)
    • UI 表明(通过 Dispatcher 确保线程安全)
    • 任务做完后释放图像内存
  4. 停止 / 完整退出

    • 调用 CompleteAdding() 告诉消费者:以后不再有新任务
    • 消费者循环自动退出

4. 核心代码示例

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Threading;
public class CameraProcessor
{
private BlockingCollection<CameraInfo> taskQueue;private CancellationTokenSource cts;private Task workerTask;private readonly Dispatcher uiDispatcher;public CameraProcessor(Dispatcher dispatcher){uiDispatcher = dispatcher;StartWorker();}private void StartWorker(){taskQueue = new BlockingCollection<CameraInfo>();cts = new CancellationTokenSource();workerTask = Task.Run(() => WorkerLoop(), cts.Token);}public void Update(CameraInfo info) => taskQueue.Add(info);private void WorkerLoop(){foreach (var info in taskQueue.GetConsumingEnumerable(cts.Token)){try{var graphic = GetGraphicBySn(info.SerialNumber);if (graphic != null){var results = Detection(graphic, info.Image);// UI 更新uiDispatcher.Invoke(() =>{graphic.StatusText = "检测完成";graphic.LastResults = results;});}info.Image?.Dispose(); // 避免内存泄漏}catch (Exception ex){Debug.WriteLine($"检测异常: {ex}");}}}public void Stop(){taskQueue.CompleteAdding();cts.Cancel();workerTask.Wait();}public void Restart(){Stop();StartWorker();}private List<YOLOData> Detection(GraphicInfo graphic, HObject image){Stopwatch sw = new Stopwatch();List<YOLOData> data = new List<YOLOData>();// 1. 预处理sw.Restart();HObject imgProduct = PreprocessImage(graphic, image);sw.Stop();long preprocessTime = sw.ElapsedMilliseconds;// 2. YOLO 推理sw.Restart();//推理~~~~~sw.Stop();long detectTime = sw.ElapsedMilliseconds;return data;}private HObject PreprocessImage(GraphicInfo graphic, HObject image){HObject imgProduct = null;if (graphic.BlobConfig.BlobEnable)imageScriptTool.BlobProduct(image, graphic.BlobConfig, out imgProduct);if (graphic.ScriptConfig.Preprocessing)imageScriptTool.Preprocess(imgProduct ?? image, graphic.ScriptConfig.PreprocessFuncName, out imgProduct);if (imgProduct == null)imgProduct = image.Clone();if (graphic.ScriptConfig.定位摆正)imageScriptTool.PosJust(image, imgProduct, out imgProduct, out HTuple FixDeg, false);return imgProduct;}private GraphicInfo GetGraphicBySn(string sn){// TODO: 根据相机序列号找到对应的 GraphicInforeturn null;}}

5. 使用建议

  1. 回调线程只入队
    避免直接在 IO 回调里做检测,防止阻塞相机触发。

  2. 后台线程消费
    WorkerLoop 永远循环消费任务,保证线程安全。

  3. UI 更新
    通过 Dispatcher.Invoke 确保 WPF 控件安全访问。

  4. 停止 / 重启

    • 程序退出时调用 Stop() → 完成队列 → 优雅退出
    • 如果需要“暂停/恢复”,可用标志位控制,而不是 CompleteAdding() 再恢复。
  5. 多相机独立 YOLO 实例
    每台相机维护独立的 YOLO 和预处理对象,避免线程竞争。


6. 总结

  • BlockingCollection<T> 是多线程生产者-消费者模式的核心利器,适合高并发图像处理场景
  • 将相机回调与耗时检测解耦,保证系统稳定
  • 完整框架支持多相机并发检测、UI 安全更新、暂停/停止控制
http://www.zskr.cn/news/14626.html

相关文章:

  • 上手 cpp-httplib:轻量级 C++ HTTP 库的安装与实战指南 - 教程
  • 题解:P9868 [NOIP2023] 词典
  • AtCoder Beginner Contest 425
  • MaopaiJD Esp8266 代码
  • Ynoi Easy Round 2015 学习笔记
  • 深入解析:5. Prompt 提示词
  • 【自学笔记】Redis 飞快入门
  • 实用指南:K8s日志架构:Sidecar容器实践指南
  • 详细介绍:开源 java android app 开发(十七)封库--混淆源码
  • Meta基础设施演进与AI技术革命
  • 完整教程:Spring AI整合聊天模型DeepSeek
  • 2025 年焚烧炉厂家 TOP 企业品牌推荐排行榜!权威甄选实力与口碑俱佳的江苏焚烧炉 / 无锡焚烧炉推荐这十家公司!
  • 2025 年防腐涂料厂家 TOP 企业品牌推荐排行榜,乙烯基、环氧煤沥青、环氧防腐涂料、防腐涂料地坪 、防腐涂料水池推荐这十家公司!
  • 深入解析:Social-Auto-Upload - 多平台社交媒体视频自动化上传工具
  • 用 C# 打造企业资产管理系统雏形——从控制台到完整模块设计 - 详解
  • 10.1刷题计划一
  • 笔记本电脑重装系统后找不到5G WIFI无线网或蓝牙模块消失的解决方案
  • 2025年确有专长培训权威推荐榜:专业资质与特色诊疗口碑之选
  • 达成设计卓越:全面解析 IC 设计中的验证之道
  • 2025 年超声波清洗机品牌最新权威推荐排行榜:龙门式 / 悬挂式 / 全自动等多类型设备厂家 TOP3 精选,助力企业精准选购
  • 详细介绍:基于Chrome140的FB账号自动化——脚本撰写(二)
  • CentOS7二进制安装包方式部署K8S集群之CA根证书生成 - 实践
  • Powershell 管理 后台/计划 作业(六)
  • java17及以上版本如何抵御TemplatesImpl注入
  • 详细介绍:【C++实战(53)】C++11线程库:开启多线程编程新世界
  • NOIP2025模拟赛28
  • markdown笔记文件批量打上时间戳
  • 十月数据结构题没做
  • 2025年未央区高端楼盘,西咸新区品质楼盘,西安高新品牌楼盘住宅口碑推荐,地建嘉信臻境周边配套丰富,教育医疗商业齐全
  • 2025年西安洋房楼盘,陕西优质楼盘,西咸新区现房楼盘住宅口碑推荐,地建嘉信臻境超2000㎡高端会所,功能多样