ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

VisionPro原生串流:图像与结果数据同步传输的工业应用实践

VisionPro原生串流:图像与结果数据同步传输的工业应用实践 如果你正在寻找一种将 VisionPro 强大的视觉处理能力“搬”到其他设备上的方法或者困惑于如何将复杂的检测结果实时传递给 PLC 或上位机那么你很可能已经接触过“串流”这个概念。传统印象里工业视觉的串流往往意味着复杂的第三方插件、额外的硬件采集卡以及令人头疼的延迟和稳定性问题。但 VisionPro 的原生串流Native Streaming功能彻底改变了这个游戏规则。它并非一个简单的视频流输出而是一个深度集成在 VisionPro 框架内的、低延迟、高保真的图像与结果数据同步传输通道。最神奇的地方在于它让你能以近乎零附加开发成本的方式将 VisionPro 实时处理中的每一帧图像、每一个工具的检测结果如坐标、角度、通过/失败状态打包成一个标准流推送给网络上的任何客户端。这意味着你可以在另一台电脑的监控软件上实时看到检测画面同时接收结构化的 JSON 数据而无需在 VisionPro 内部做复杂的 TCP/IP 通信开发。本文将深入解析 VisionPro 原生串流的核心机制、适用场景并通过一个从环境配置到代码实现的完整案例展示如何一步步搭建一个可用的图像与结果同步流。你会发现它解决的远不止“远程查看”这么简单而是为集中监控、数据归档、AI二次分析、与MES/SCADA系统集成打开了新的大门。1. 原生串流它到底解决了什么痛点在深入技术细节前我们首先要明确为什么需要串流仅仅是为了远程桌面查看 VisionPro 界面吗显然不是。远程桌面如 RDP、VNC传输的是整个屏幕的像素压缩延迟高、带宽占用大且无法直接获取 VisionPro 内部的结构化数据。VisionPro 原生串流瞄准的是以下几个工业场景中的核心痛点集中监控与看板生产线经理需要在办公室大屏上同时监控多台视觉工位的实时状态。传统方案需要为每台工位部署采集卡和工控机成本高昂。串流允许直接将每个 VisionPro 工位的处理画面和结果推送至中央服务器实现低成本集中可视化。过程数据归档与追溯当出现不良品时不仅需要记录“NG”结果更需要将导致 NG 的那一帧图像及所有中间处理数据如轮廓、测量值保存下来。原生串流可以在传输实时流的同时触发高分辨率原图保存实现数据与图像的精确关联。与上层系统MES/SCADA集成MES 系统需要接收视觉检测的详细结果而不仅仅是 OK/NG 信号。通过串流VisionPro 可以将包含产品ID、尺寸、缺陷类型等丰富信息的 JSON 数据实时推送给 MES 的接口服务。AI模型协同处理可以在 VisionPro 完成定位和预处理后将 ROI 区域图像通过串流发送给另一台部署了深度学习推理服务器如 NVIDIA Triton进行更复杂的缺陷分类再将结果返回实现传统视觉与 AI 的高效混合。原生串流的本质是VisionPro 工作流程的标准化、网络化输出接口。它把原本封闭在单一设备内的视觉处理流水线变成了一个可订阅的网络服务。2. 核心概念与工作原理拆解理解原生串流需要掌握几个关键概念流Stream一个连续的数据序列。在 VisionPro 中一个流通常对应一个相机采集会话Acquisition Session或一个视觉工具链的处理流程。每个流有唯一的名称Stream Name。发布者PublisherVisionPro 应用程序扮演的角色。它负责将图像和关联的元数据Metadata打包并按照指定协议如 RTSP、WebSocket发布到网络上。订阅者Subscriber任何能够理解该协议的客户端程序。可以是 VLC 播放器、自定义的 C#/Python 客户端甚至是另一个 VisionPro。元数据Metadata这是串流的“灵魂”。它不仅仅是图像像素而是附着在图像上的结构化信息。这可以包括采集时间戳、帧号。视觉工具的结果如CogPMAlignTool的Score和TranslationX/Y。自定义的检测结果通过CogToolBlock输出的UserResult。任何你通过脚本添加到CogImage8Grey或CogImage24PlanarColor的UserData字典中的数据。工作原理流程图解[相机硬件] | (采集图像) v [VisionPro 采集框架] | (触发、取图) v [视觉工具链处理] (CogPMAlignTool, CogCaliperTool, CogToolBlock...) | (生成结果、元数据) v [原生串流模块] (将图像编码 元数据序列化) | (封装成标准网络流协议) v [网络] (RTSP, WebSocket...) | v [客户端] (解码图像 解析元数据用于显示、分析、存储)关键在于图像和元数据是严格同步的。客户端收到一帧图像时可以同时从协议的数据通道如 RTSP 的 RTP 载荷或 WebSocket 消息中提取出对应此帧的所有检测结果避免了自行解析图像或通过其他通信方式同步数据带来的复杂性和误差。3. 环境准备与前置条件在开始编码前请确保你的开发环境满足以下要求VisionPro 版本确保安装的 VisionPro 版本支持原生串流功能。该功能在较新的版本中成为标准组件例如 VisionPro 9.x 及以上。建议使用最新版本以获得最佳性能和功能支持。开发环境主开发机安装 VisionPro 和 Visual Studio推荐 2019 或 2022。VisionPro 设计器QuickBuild和 .NET 类库将在此使用。客户端测试机一台可以访问主开发机网络的电脑。用于运行客户端程序接收流。操作系统可以是 Windows、Linux 或 macOS。网络确保两台机器在同一局域网内防火墙已配置允许相关端口通信默认 RTSP 端口 554或自定义的 WebSocket 端口。权限以管理员身份运行 Visual Studio 和 VisionPro QuickBuild以避免权限问题。基础知识熟悉 VisionPro QuickBuild 的基本操作了解如何配置 Job、ToolBlock以及简单的 C# 脚本编写。4. 在 QuickBuild 中配置串流发布者我们将从一个简单的“定位与测量”Job 开始为其添加串流功能。步骤 1创建或打开一个 VisionPro Job在 QuickBuild 中创建一个新的 Job 或打开现有 Job。假设这个 Job 包含一个CogAcqFifoTool采集、一个CogPMAlignTool模板定位和一个CogCaliperTool卡尺测量。步骤 2添加 Streaming 工具在 QuickBuild 的工具箱中搜索并找到CogStreaming相关工具。通常你会使用CogStreamingServerTool。将其拖放到 Job 的流程中。步骤 3配置流服务器选中CogStreamingServerTool在其属性窗口中配置服务器参数Stream Name: 输入一个唯一的流名称例如“ProductionLine_Station1”。客户端将通过此名称订阅。Port: 设置服务器监听的端口号例如8554。Transport Protocol: 选择协议。RTSP是通用性最强的选择兼容 VLC、FFmpeg 等大多数播放器。WebSocket更适合需要与 Web 前端如浏览器或自定义脚本交互的场景。Encoding: 选择图像编码格式。H.264或HEVC可以大幅降低带宽适合网络传输MJPEG则延迟更低但带宽占用高。根据网络条件和客户端兼容性选择。步骤 4绑定图像源与元数据这是最关键的一步。我们需要告诉串流服务器发送哪张图像以及附带上哪些数据。图像源在CogStreamingServerTool的属性中找到Image Source或类似的输入项。将其链接到你的采集工具如CogAcqFifoTool的OutputImage。这样每一帧采集到的图像都会被送入流。元数据Metadata元数据需要通过 VisionPro 的“用户数据”User Data机制来附加。首先我们需要将视觉工具的结果写入图像的UserData字典。这通常在 Job 的Run事件脚本中完成。打开 Job 的脚本编辑器找到Run事件或其他适当的处理完成事件。步骤 5编写脚本附加元数据以下是一个示例脚本将 PMAlign 和 Caliper 的结果添加到当前图像的UserData中以便串流工具自动拾取。// 文件VisionPro Job 的 Run 事件脚本 // 假设工具实例名称为CogPMAlignTool1, CogCaliperTool1 public class UserScript : CogToolBlockBase { public override void Run() { // 获取当前正在处理的图像 CogImage8Grey currentImage (CogImage8Grey)Image; // 准备一个字典来存储我们想要发送的元数据 // 键名可以自定义但建议保持清晰和一致 System.Collections.Generic.Dictionarystring, object streamMetadata new System.Collections.Generic.Dictionarystring, object(); // 1. 添加 PMAlign 结果 if (CogPMAlignTool1.Results ! null CogPMAlignTool1.Results.Count 0) { CogPMAlignResult result CogPMAlignTool1.Results[0]; streamMetadata[PMAlign_Score] result.Score; streamMetadata[PMAlign_X] result.GetPose().TranslationX; streamMetadata[PMAlign_Y] result.GetPose().TranslationY; streamMetadata[PMAlign_Rotation] result.GetPose().Rotation; streamMetadata[PMAlign_Found] result.Score 0.8; // 自定义判断逻辑 } else { streamMetadata[PMAlign_Found] false; } // 2. 添加 Caliper 结果 if (CogCaliperTool1.Results ! null CogCaliperTool1.Results.Count 0) { CogCaliperResult result CogCaliperTool1.Results[0]; streamMetadata[Caliper_Width] result.Width; streamMetadata[Caliper_EdgesFound] result.Edges.Count; // 可以添加更多边缘细节... } // 3. 添加时间戳和帧号等系统信息 streamMetadata[Timestamp_UTC] System.DateTime.UtcNow.ToString(o); streamMetadata[FrameID] currentImage.SelectedSpaceName; // 或用其他方式获取帧ID // 将元数据字典赋值给图像的 UserData。 // CogStreamingServerTool 会自动查找并发送 Image.UserData 中的内容。 currentImage.UserData streamMetadata; // 重要确保后续工具如果有能接收到带有 UserData 的图像 // 通常Run事件脚本在工具链最后执行所以直接赋值即可。 } }步骤 6配置流工具使用 UserData在CogStreamingServerTool的属性中确保其配置为自动发送Image.UserData作为元数据。通常有一个Include UserData或Metadata Source的选项将其设置为From Image或类似选项。步骤 7运行与测试在 QuickBuild 中运行你的 Job。打开CogStreamingServerTool的属性窗口它可能会显示一个状态信息如“Streaming on rtsp://你的IP:8554/ProductionLine_Station1”。记下这个 RTSP URL。5. 客户端接收与解析一个完整的 C# 示例现在我们创建一个简单的 C# Windows Forms 客户端程序来接收流并显示图像和解析元数据。步骤 1创建新的 C# Windows Forms App 项目步骤 2安装 NuGet 包我们需要一个能处理 RTSP 流并解码 H.264/MJPEG 的库。LibVLCSharp是一个优秀的跨平台选择。同时我们需要Newtonsoft.Json来解析元数据如果元数据以 JSON 格式发送。 在 NuGet 包管理器中安装VideoLAN.LibVLC.Windows(根据你的系统选择 Win32/x64)LibVLCSharp.WinFormsNewtonsoft.Json步骤 3设计窗体在 Form 上放置以下控件一个Panel控件命名为videoPanel用于承载视频渲染。一个TextBox控件命名为rtspUrlBox用于输入 RTSP URL。一个Button控件命名为connectButton用于连接/断开。一个RichTextBox控件命名为metadataBox用于显示解析出的元数据。一个PictureBox控件命名为snapshotBox用于显示快照可选。步骤 4编写客户端代码// 文件Form1.cs using System; using System.Collections.Generic; using System.Windows.Forms; using LibVLCSharp.Shared; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace VisionProStreamClient { public partial class Form1 : Form { private LibVLC _libVLC; private MediaPlayer _mediaPlayer; private bool _isConnected false; public Form1() { InitializeComponent(); Core.Initialize(); // 初始化 LibVLC _libVLC new LibVLC(); _mediaPlayer new MediaPlayer(_libVLC); // 将 MediaPlayer 的视频输出绑定到 Panel _mediaPlayer.Hwnd videoPanel.Handle; } private void connectButton_Click(object sender, EventArgs e) { if (!_isConnected) { string rtspUrl rtspUrlBox.Text.Trim(); if (string.IsNullOrEmpty(rtspUrl)) { MessageBox.Show(请输入 RTSP URL); return; } using (var media new Media(_libVLC, new Uri(rtspUrl))) { // 关键设置选项以接收“sap”元数据VisionPro 通过此通道发送 // 并启用网络缓存以减少延迟 media.AddOption(:sap); media.AddOption(:network-caching100); // 缓存100ms可调整 _mediaPlayer.Play(media); _mediaPlayer.SetMarqueeString(VideoMarqueeOption.Text, Connected to: rtspUrl); // 订阅元数据事件 _mediaPlayer.MetaChanged MediaPlayer_MetaChanged; connectButton.Text 断开; _isConnected true; } } else { _mediaPlayer.Stop(); _mediaPlayer.MetaChanged - MediaPlayer_MetaChanged; connectButton.Text 连接; metadataBox.Clear(); _isConnected false; } } // 当流的元数据更新时触发此事件 private void MediaPlayer_MetaChanged(object sender, MediaPlayerMetaChangedEventArgs e) { // VisionPro 发送的自定义元数据通常存储在 Description 或自定义字段。 // 我们需要检查 MediaPlayer 的当前 Media 对象。 if (_mediaPlayer.Media ! null) { // 尝试从 Media 的元数据中获取。VisionPro 可能使用特定键如 “visionpro-metadata”。 // 更可靠的方式是解析 ESElementary Stream信息但这更复杂。 // 一个常见实践是VisionPro 将 JSON 字符串作为流的“标题”或“描述”发送。 string metadataJson _mediaPlayer.Media.Meta(MetadataType.Description); if (!string.IsNullOrEmpty(metadataJson)) { // 在 UI 线程上更新文本框 this.Invoke(new Action(() { try { // 使用 Newtonsoft.Json 解析 JObject metaObj JObject.Parse(metadataJson); // 格式化输出 metadataBox.Text JsonConvert.SerializeObject(metaObj, Formatting.Indented); // 示例提取特定字段并做逻辑判断 if (metaObj[PMAlign_Found] ! null (bool)metaObj[PMAlign_Found] false) { metadataBox.BackColor System.Drawing.Color.LightPink; // 高亮显示未找到 } else { metadataBox.BackColor System.Drawing.Color.White; } } catch (JsonReaderException ex) { metadataBox.Text 元数据解析错误 (非JSON): metadataJson Environment.NewLine 错误: ex.Message; } })); } else { // 如果没有 Description可以尝试其他 Meta 类型如 Title或解析子项目 // 这里简化处理实际可能需要更深入的 LibVLC API 调用。 } } } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { _mediaPlayer?.Stop(); _mediaPlayer?.Dispose(); _libVLC?.Dispose(); } } }步骤 5运行与验证运行你的 VisionPro Job确保CogStreamingServerTool正在运行并显示 URL。运行此 C# 客户端程序。在rtspUrlBox中输入 VisionPro Job 显示的 RTSP URL例如rtsp://192.168.1.100:8554/ProductionLine_Station1。点击“连接”按钮。你应该能在videoPanel中看到实时的视频流。同时metadataBox中会不断更新并格式化显示从流中接收到的 JSON 元数据包括 PMAlign 的分数、坐标以及卡尺的宽度等。6. 进阶使用 WebSocket 与 Web 前端集成对于需要浏览器端监控的场景RTSP 可能不是最佳选择浏览器原生不支持。此时可以使用 VisionPro 的WebSocket 流。在 VisionPro 端的配置变更在CogStreamingServerTool的属性中将Transport Protocol改为WebSocket。设置WebSocket Port例如9001。WebSocket 通常传输的是 MJPEG 帧和附加的 JSON 元数据编码选择MJPEG可能更简单。Web 前端客户端示例 (HTML JavaScript):创建一个简单的index.html文件。!DOCTYPE html html head titleVisionPro Web Stream/title script srchttps://cdn.jsdelivr.net/npm/hls.jslatest/script !-- 如果需要HLS否则用img标签 -- style #videoContainer { width: 640px; height: 480px; border: 1px solid #ccc; } #metadata { white-space: pre-wrap; font-family: monospace; height: 200px; overflow-y: scroll; border: 1px solid #ccc; padding: 5px;} /style /head body h2VisionPro WebSocket Stream Viewer/h2 div input typetext idwsUrl valuews://192.168.1.100:9001/ProductionLine_Station1 size50/ button onclickconnectStream()连接/button button onclickdisconnectStream()断开/button /div br/ div idvideoContainer img idvideoImage styledisplay:none; width:100%; height:100%;/ /div br/ div元数据/div div idmetadata/div script let websocket null; let imageElement document.getElementById(videoImage); let metadataDiv document.getElementById(metadata); function connectStream() { const url document.getElementById(wsUrl).value; if (!url) { alert(请输入 WebSocket URL); return; } websocket new WebSocket(url); websocket.onopen function(event) { console.log(WebSocket 连接已打开); metadataDiv.innerHTML 连接成功\n; }; websocket.onmessage function(event) { // VisionPro WebSocket 流通常发送二进制数据。 // 消息结构可能是前4字节为元数据长度 (n)接着 n 字节的 JSON 元数据然后是 JPEG 图像数据。 const data event.data; if (data instanceof Blob) { const reader new FileReader(); reader.onload function() { const arrayBuffer reader.result; const dataView new DataView(arrayBuffer); // 假设前4字节32位整数是元数据长度 const metaDataLength dataView.getUint32(0, true); // little-endian const textDecoder new TextDecoder(utf-8); const metaDataJson textDecoder.decode(arrayBuffer.slice(4, 4 metaDataLength)); const imageBlob new Blob([arrayBuffer.slice(4 metaDataLength)], { type: image/jpeg }); // 显示元数据 try { const metaObj JSON.parse(metaDataJson); metadataDiv.innerHTML JSON.stringify(metaObj, null, 2) \n---\n metadataDiv.innerHTML; } catch(e) { metadataDiv.innerHTML 元数据解析错误: e.message \n metadataDiv.innerHTML; } // 显示图像 const imageUrl URL.createObjectURL(imageBlob); imageElement.src imageUrl; imageElement.style.display block; }; reader.readAsArrayBuffer(data); } else { // 如果是文本消息可能是纯JSON元数据图像通过其他方式如MJPEG over HTTP console.log(收到文本消息:, data); metadataDiv.innerHTML data \n---\n metadataDiv.innerHTML; } }; websocket.onerror function(error) { console.error(WebSocket 错误:, error); metadataDiv.innerHTML 连接错误\n; }; websocket.onclose function(event) { console.log(WebSocket 连接关闭); metadataDiv.innerHTML 连接已关闭\n; imageElement.style.display none; }; } function disconnectStream() { if (websocket websocket.readyState WebSocket.OPEN) { websocket.close(); } } /script /body /html这个示例假设 VisionPro 的 WebSocket 流采用了一种简单的封装格式先发送元数据长度再发送元数据 JSON 字符串最后发送 JPEG 图像二进制数据。实际的封装格式需要根据 VisionPro 的文档或通过分析网络包来确定。你可能需要调整onmessage中的解析逻辑。7. 常见问题与排查思路问题现象可能原因排查方式解决方案QuickBuild 中流服务器状态显示“未激活”或“错误”端口被占用防火墙阻止编码器不支持。1. 检查端口是否被其他程序占用netstat -ano。2. 暂时关闭防火墙测试。3. 查看 QuickBuild 输出窗口或 Windows 事件查看器中的错误信息。1. 更换端口。2. 在防火墙中为 VisionPro 或对应端口添加入站规则。3. 尝试更换编码格式如 H.264 改为 MJPEG。客户端能连接但看不到图像黑屏客户端解码器不支持流的编码格式网络带宽不足或延迟过高流地址错误。1. 使用 VLC 播放器测试同一地址VLC 解码能力强。2. 在 QuickBuild 中降低流的分辨率或帧率。3. 确认客户端程序正确订阅了视频轨道。1. 在 VisionPro 端更换为更通用的编码如 MJPEG。2. 优化网络或使用有线连接。3. 检查客户端代码确保正确初始化和播放 Media。客户端能收到图像但收不到元数据元数据未正确附加到图像客户端未正确解析元数据通道。1. 在 VisionPro Job 的 Run 脚本中调试输出currentImage.UserData的内容确认数据已写入。2. 使用 Wireshark 抓包分析 RTSP/RTP 流查看是否有附加数据。3. 检查客户端代码中订阅元数据的事件和方法是否正确如 LibVLC 的MetaChanged事件。1. 确保脚本在流工具之前执行且UserData被正确赋值。2. 确认 VisionPro 流工具配置中已启用“包含 UserData”。3. 查阅 VisionPro 帮助文档确认元数据的确切发送方式如通过 RTSP 的sap属性或自定义头。可能需要调整客户端解析逻辑。流延迟非常高500ms编码复杂度过高网络缓存设置过大客户端处理慢。1. 在 VisionPro 端尝试使用 MJPEG 而非 H.264编码延迟更低。2. 降低图像分辨率。3. 检查客户端播放器的缓存设置如 LibVLC 的network-caching参数。1. 在图像质量可接受范围内选择延迟更低的编码。2. 将 VisionPro 端和客户端的缓存参数调至最小如 50-100ms。3. 确保客户端图像渲染不是瓶颈。WebSocket 连接被拒绝端口未开放VisionPro WebSocket 服务未启动跨域问题CORS。1. 确认 VisionPro Job 正在运行且 WebSocket 端口配置正确。2. 使用telnet IP 端口测试端口连通性。3. 浏览器控制台查看 WebSocket 连接错误详情。1. 检查防火墙设置。2. 确保 VisionPro 的 WebSocket 传输协议已选中并配置。3. 对于本地测试可以暂时禁用浏览器安全策略或通过本地 Web 服务器如 IIS Express, nginx代理请求。8. 最佳实践与工程建议流命名规范化为生产线上的每个视觉工位设计清晰的流名称规范例如LineA_Station3_Inspection。这便于客户端自动发现和订阅。元数据结构设计提前规划好元数据的 JSON 结构。建议包含固定字段如deviceId,timestamp,frameIndex以及动态的results对象来存放各个视觉工具的输出。保持向后兼容性。错误处理与重连在客户端实现稳健的重连机制。网络波动时自动尝试重新连接流服务器并记录断开连接的时间点以便数据追溯。安全考虑网络隔离将视觉系统网络与办公网络进行物理或 VLAN 隔离。访问控制如果 VisionPro 版本支持配置流的访问密码或 IP 白名单。数据加密对于敏感检测数据考虑在应用层对元数据进行加密后再通过流传输。性能优化按需流式传输如果不是所有客户端都需要全分辨率全帧率可以在 VisionPro 端创建多个流针对不同用途如监控、存档设置不同的分辨率、帧率和编码参数。硬件加速确保 VisionPro 所在工控机支持所选编码格式的硬件加速如 Intel Quick Sync Video, NVIDIA NVENC。客户端去耦不要让客户端处理逻辑阻塞视频解码和渲染线程。使用生产者-消费者模式将元数据解析和业务逻辑放在独立线程中。与数据系统集成将客户端设计为流处理器而非单纯的查看器。它可以同时做三件事显示视频、将元数据写入时序数据库如 InfluxDB、将关键事件如 NG推送到消息队列如 RabbitMQ/Kafka供 MES 消费。版本管理当 VisionPro Job 的工具链或元数据格式更新时需同步更新客户端解析逻辑。可以考虑在元数据中加入version字段客户端根据版本号采用不同的解析器。VisionPro 的原生串流功能将强大的机器视觉处理能力从单一的设备中解放出来使其成为一个可网络化访问的服务。它不仅仅是“远程查看”而是构建现代化、分布式视觉检测系统的关键拼图。通过本文的详细步骤你应该能够搭建起从图像采集、处理到结果同步推送的完整链路。下一步你可以尝试将多个工位的流汇聚到一个统一的 .NET Core 或 Python 服务中实现集中管理和数据聚合。探索使用FFmpeg命令行工具接收 RTSP 流并直接录制为带有元数据字幕的视频文件用于长期归档。结合Grafana等可视化工具将接收到的元数据如尺寸趋势、良率实时展示在监控大屏上。当你掌握了这项技术你会发现视觉系统的边界被极大地扩展了。
返回列表