
1. 从“单点跑通”到“整机联动”Group模块到底解决了什么熟悉海康VisionMaster的朋友应该都有这种体会刚上手时拖几个定位、测量模块连成一条流程跑通一个静态检测Demo成就感拉满。但真到了做项目——产线上几十个相机、几十种工件、还得和PLC握手、按节拍跑——你会发现单条流程根本不够用。这时候你在VM里绕不开的一个东西就是Group模块。先说个容易混淆的点VisionMaster里的“流程”和“Group”不是一回事。一个流程文件里可以建多个Group每个Group就是一张独立的流程图。这就像写代码时一个解决方案Solution里可以挂多个项目Project每个项目都有自己的入口和逻辑。我之前接过一个项目一条产线上要同时检测一个工件的正反面还有一道尺寸测量工序三个工位共用一台工控机。如果只用一个流程图去串图像源、相机触发、结果输出全部搅在一起改一处就要重新捋半天调试时候人都麻了。后来改成三个Group每个Group各自独立跑一路流程问题一下就清爽了。Group模块本质上就是一个“流程容器 调度器”。它管的不只是“把几个算子串起来”还负责管相机触发、流程间的数据传递、执行状态上报、对外通讯TCP、串口、IO等的核心调度。可以说Group是VM软件里承上启下的关键单元往上一层它接受方案Solution的管理往下一层它调度流程内部的每一个模块节点。所以这篇笔记我就打算把Group模块的底层逻辑、实际搭建步骤、多Group协作的坑一次性说透。适合正在搞VisionMaster二次开发或者现场调试的朋友也适合刚入门、被各种模块搞得晕头转向的新手。2. 先搞懂Group在VM工程里的位置和作用2.1 Group与流程、方案的组织关系在VisionMaster里层级关系从大到小大致是方案文件.sol - 流程.flow / 方案内的流程列表 - Group - 流程节点算子模块。你在软件左侧会看到一个“流程”面板里面可以添加多个Group。新建的Group默认会包含几个基础模块图像源、结果数据格式化输出等。图像源负责取图可以是相机实时采集也可以是本地图片、SDK回调图像结果模块负责把这一路流程的输出整理好用于显示、存储或对外发送。这里是第一个关键认知一个Group实际上是“一条独立的处理流水线”它有自己的触发方式、执行状态和输出终点。多个Group之间可以通过“全局变量”或“共享数据”进行数据交互但它们的执行是相对独立的——这就为多相机或多工位的并行结构提供了基础。2.2 为什么说Group是模块化调试的最小单位我在调试时习惯把每一个Group当作一个可独立运行的小程序来对待。这样有个很实际的好处出问题时不用整条流水线停下来排查。比如工位2的相机老是丢图那我单独跑工位2对应的那个Group看看图像源那块有没有问题、触发信号有没有到不影响工位1和工位3继续跑。另外Group是VM执行引擎的最小调度单位。你在VM里点“开始运行”时系统并不是把整个方案的所有模块一股脑全部启动而是按Group的配置逐个启动。每个Group可以设置“连续运行”“单次运行”“软触发”等不同模式。这种设计对现场调试极友好——哪个环节要单独验证直接把其他Group停掉就行。这里也要提醒一句如果多个Group共用同一个相机资源千万别把所有Group都设成自动运行不然会出抢占相机的冲突。我早期就吃过这个亏两个Group都连了同一个相机一运行就报“相机被占用”排查了半天才发现是资源冲突。3. 手把手搭建一个Group流程3.1 新建Group与基础图像源配置建立新方案后默认会有一个Group0。右键“流程”区域可以新建Group命名最好别用默认的Group0、Group1按工位或功能命名比如“AOI_正面检测”“测量_工位2”——大项目里几十个Group靠名字找比靠编号找效率高太多。接下来配置图像源。双击图像源模块在配置界面里选择相机。海康的相机直接用GigE或USB3.0接口就能枚举出来第三方相机可以选择SDK方式或者用“图像源”模块里的“图像输入- SDK”选项配置好回调函数就行。这里有一个实操细节图像源模块的“取流模式”建议直接设为“硬触发”相机IO触发或者“软触发”指令触发在工业现场尽量不要用“连续采集”。连续采集意味着相机一直在出图CPU和带宽被无意义地占用还会导致图像缓存堆积触发时取到的图不是最新的就会出“图不对件”的严重事故。3.2 图像处理流程的搭建与模块连接建好Group、配好图像源之后就可以像搭积木一样连接处理模块了。VM的连线规则是左侧输入、右侧输出。以定位操作为例从模块库里拖一个“模板匹配”到流程图上将图像源输出口的“图像”连接到模板匹配的“输入图像”引脚再配置模板、设置匹配参数和输出结果即可。连接的先后顺序很重要但不是所有模块都要连图像。比如“几何测量”模块输入既可以是图像也可以是上一级定位模块输出的点、线等几何数据。这里要对齐输出引脚的数据类型看到引脚颜色不匹配通常就是类型对不上。连线时有个小技巧按住鼠标左键从输出引脚拖到输入引脚松开就完成连接。要删除连线右键选择删除即可。需要注意的是一个模块可以同时把结果输出给下游多个模块比如把定位结果同时给测量模块和OK/NG判断模块这在实际项目中非常常用。3.3 让Group“跑起来”的三种触发套路Group的执行触发是一个必须讲明白的点。VM里Group的触发模式有连续自动、单次执行、软触发等选项实际项目中最常用的是以下三种第一种连续运行模式。适用于Demo验证和静态调试。打开运行后Group会以最快速度循环执行流程图你换了图像源参数立即能看到效果。第二种软触发模式。通过外部指令例如调用VM的SDK接口或者通讯指令触发一次Group执行。这种方式在二次开发中最常用因为可以和上位机的工艺逻辑对齐做到“要一张、处理一张、回传一个结果”。第三种硬触发模式。相机收到外部信号比如光电传感器后采集图像图像到位后触发Group执行。这种模式延迟最低适合高速产线但配置起来也最复杂——不仅要配相机的触发源还要在VM里做好触发帧同步。从稳定性角度我优先推荐硬触发或软触发。连续运行虽然调试方便但一旦图像源没有新图或者执行时间波动结果就会乱套。做产线项目时不要图省事开连续模式。4. 进入Group内部核心机制和关键参数的深度解读4.1 流程执行的同步阻塞与异步处理很多初学者会问Group里的模块是并行跑的还是一个一个跑默认情况下一个Group内的模块按照连线顺序串行执行——上一个模块处理完结果传给下一个下一个才开始。直播里你看到的VM“跑起来很流畅”那是因为每个模块处理耗时极短人眼感知不到串行停顿。但在多相机场景瓶颈就很明显了。比如一个Group里有两个模板匹配各自要处理一整张图串行下来总耗时就是二者之和。这时就需要用“分支流程”或者“并行执行”的技巧。VM里可以通过“条件分支”或“逻辑分支”将流程拆成多个路径让互不依赖的计算同时进行再在汇合点做结果合并。注意虽然VM内部会做一定程度的并行加速但流程逻辑上的并行要靠你自己设计。Group的内部还有一个容易忽视的点模块的“启用/停用”状态。在流程图上选中一个模块右键可以停用。停用后该模块不参与执行但连线还在输出引脚没有有效数据。现场排查问题时如果你怀疑某个模块异常可以先停用再观察上下游数据变化不用删掉重连。4.2 图像数据流与非图像数据流的区别在Group流程里连线传递的数据分为图像数据和非图像数据两大类。图像数据就是相机采集到的原始图像或者经过预处理后的图像比如滤波后的、二值化后的特点是数据量巨大但下游绝大多数视觉模块都需要它。非图像数据包括定位结果坐标、角度、测量结果长度、直径、识别结果条码字符串、判定结果OK/NG等特点是结构化、量小用于逻辑判断和通讯输出。在连接模块时这两种数据流的走向要清晰地分开。比如模板匹配模块从图像源接收“图像”输出“匹配结果”非图像数据后续的“几何测量”模块既可以接收图像自己重新做边缘查找也可以直接接收匹配结果里的坐标点做测量。不同选择直接影响处理速度和精度。我的习惯是能直接用结构化结果就不重新对图像做处理速度快、稳定性高但前提是上游模块的定位精度要可靠。4.3 全局变量与跨Group数据交换单个Group内部的数据传递靠连线就好但多个Group之间需要共享数据时就要用到全局变量。全局变量的本质是存储在方案级别的一块命名空间任何Group都可以读写。设置方式是在“全局变量”面板里新建变量比如“strResult”字符串类型或“boolOK”布尔类型。然后在Group内部用“变量赋值”模块把输出结果写入全局变量。另一个Group的“条件判断”模块就可以读取这个全局变量来做业务逻辑。放下一个真实案例。我之前做的一个项目两个Group分别检测工件的上下表面最终需要把两个表面的结果汇总到一起判断整件是否合格。我的做法是GroupA检测完把布尔结果写入“IsTopOK”GroupC检测完写入“IsBottomOK”然后第三个Group专门做结果汇总在收到两个Group的“流程结束”信号后用“逻辑与”把这两个全局变量读出来得到最终OK/NG再通过通讯模块发送给PLC。这样三个Group各自独立但数据是联动的升级维护都很方便。有一点要注意全局变量读写存在时序问题。GroupA写变量GroupB读变量时如果GroupA还没执行完B读到的就是旧值。所以跨Group通信时一定要在Group的“结束信号”发出后再让下游去读。或者用“等待”模块做同步保证先执行完再读取。5. 多Group编排的艺术并行、主从与流水线模式5.1 多Group并行处理的资源分配在VM方案里创建多个Group并不难难的是如何合理分配它们之间的执行逻辑和系统资源。首先要明确多Group并行处理不等于“多个Group同时跑就一定快”。如果这些Group共用同一个CPU、同一个GPU那么在CPU核数有限的情况下并行反而会让每个Group的执行时间变长。所以并行之前先评估资源工控机的CPU是几核几线程每个Group的图像分辨率多大、算法复杂不复杂有没有使用GPU加速模块如深度学习推理我的经验是CPU核数足够比如6核以上且单个Group耗时较短小于50毫秒时多Group并行收益明显。如果某个Group特别重大图深度学习、耗时几百毫秒那尽量给它单独分配线程优先级甚至考虑用多台工控机分布式处理不要硬塞在同一台机器上。5.2 串联执行与“握手”信号设计另一种常见模式是串联执行GroupA跑完给GroupB发信号GroupB再跑。这种模式常用在流水线工序上——第一道工序检测完位置第二道工序根据位置做精准测量或贴装。串联的关键在于信号设计。VM里Group之间可以通过“结束信号”加“延迟”或“等待”模块协调。更稳定的做法是让上位机C#、WPF程序通过SDK控制上位机调用“开始执行GroupA”的接口等收到GroupA的结束回调后再触发GroupB。这种“握手”模式把时序控制权交给上位机出错时便于统一处理。在这里要强调一个很多人踩过的坑如果直接在VM里让GroupA和GroupB同时运行又互相等待着对方的数据非常容易造成死锁。你会看到两个Group都在“运行中”但流程卡住不动也不会报错只有用任务管理器查看CPU占用才发现两个进程都在空转这就是典型的跨Group等待死锁。解决方法是理清数据依赖方向避免环形等待。5.3 主从模式一个调度Group控制多个执行Group对于复杂的自动化设备我更推荐“主从模式”——总调度Group负责逻辑编排执行Group负责具体的图像处理。打个比方总调度就是工头执行Group就是干活的工人。工头接到PLC的启动指令后给工人1、工人2下达任务等工人都干完活、交回结果工头汇总后再上报PLC。这样做的好处是逻辑集中调试方便。比如要临时跳过某道检测比如生产测试模式不需要测量工序我只需要在总调度Group里屏蔽掉对应的“触发执行”模块即可不用改动执行Group内部的算法流程。搭建主从模式时总调度Group通常包含通讯接收模块接收PLC指令、变量赋值模块下发任务、逻辑判断模块判断各Group返回的状态以及触发执行模块用SDK调用或者VM内部的“运行其他Group”功能。执行Group则保持内部流程干净——只管图像处理做完把结果写到全局变量发一个“完成”信号。6. 常见问题与排查技巧实录6.1 相机占用冲突多个Group抢同一个相机源现象两个Group都配置了同一个相机作为图像源运行时提示相机打开失败或被占用。原因很简单相机是独占资源同一时刻只能被一个进程或一个Group实例占用。VM里虽然多个Group属于同一个方案但每个Group的图像源模块会尝试独立打开相机设备就会冲突。解决思路不要让多个Group直接连接同一个物理相机。正确做法有两种一是用VM的“相机共享”机制如果你的版本支持通过图像源共享使多个Group从同一路取流中获取图像。二是只让其中一个Group连接相机处理完图像后把结果通过全局变量分发给其他Group。如果非得在多个Group中独立使用同一相机的不同算法可以用“取流缓存”的方式相机采集的图像存入共享缓存其余Group从缓存中读取图像。6.2 执行顺序错乱Group内部模块执行顺序不受控有些朋友会遇到这种情况明明上一个模块还没执行完下一个模块就已经在跑了或者结果不对。第一个检查点连线是否连对了。第二个检查点是否误开了模块的“异步执行”属性。VM中部分模块如通讯发送、文件保存支持异步模式开启后主流程不等它执行完就继续往下走。如果你对时序有严格要求把这些模块设置为同步模式。还有一种情况模块之间有数据依赖但没连线你只是把两个模块放在同一个流程图上以为它会按顺序执行。这就大错特错了。VM不是按模块排列顺序执行而是按连线拓扑顺序执行。没有任何连线关系的模块它们之间是相互独立的执行顺序没有保证。所以画清楚每一条连线就等于写清楚了执行逻辑。6.3 运行慢Group执行耗时飙升遇到Group跑得慢别急着优化算法先用VM的“模块耗时统计”功能把每个模块的实际耗时拉出来看看。VM的界面下方或模块属性里能看到每个模块的执行耗时这是定位性能瓶颈最直接的手段。统计出来之后有两种情况最值得注意。一是某个模块输入图像分辨率太大即便是预处理模块如高斯滤波也会因为图像像素量太多而变慢。解决办法是在不影响精度的前提下先缩小感兴趣区域ROI只处理需要的区域。二是连续运行模式下图像源取流和处理速度不匹配导致图像队列越积越多。解决办法是开启“丢帧”策略——处理不过来时丢弃最旧的未处理图像保证实时性而不是无限积压。6.4 数据异常跨Group共享数据读到旧值这种“离奇Bug”非常难排查有时结果是对的有时是错的完全没有规律。后来跟踪变量才发现读取全局变量时另一个Group还没把最新结果写进去。解决方案是确保信号的先后顺序——被依赖的Group先执行完再触发依赖方。如果使用上位机SDK就严格采用“执行完再触发下一个”的同步回调模式如果完全依赖VM内部逻辑可以在读变量前加“等待指定信号”的条件模块。还有一个小细节全局变量定义时初始值一定要设置合理。比如布尔变量“IsOK”的初始值建议设置为FalseNG。这样就算出现时序问题导致变量没被更新下游也不会误判成OK——宁可“漏杀”也不能“放水”这属于工业安全的底线思维。7. 二次开发视角用SDK控制Group执行7.1 为什么需要SDK方式调度GroupVM软件本身的操作界面虽然方便但产线上的真实情况是操作员不可能天天对着VM界面点鼠标他们面对的是设备触摸屏或者上位机软件。所以项目落地往往都要做二次开发——用C#、C等语言调用VisionMaster的SDK把Group嵌到自己的程序界面里实现自动运行、结果显示、参数下发等功能。SDK方式调度Group还有一个好处可以灵活控制“何时执行哪个Group”把图像处理的节奏和整个设备的工艺流程完美对齐。比如设备启动时先回零到位后给相机发触发信号收到图像后调用指定Group处理得到结果后控制气缸动作这套动作全部由上位机协调VM只负责“被调用时执行并返回结果”。7.2 一个典型的C#调度Group流程下面是简化版的调用思路伪代码级别实际项目中还需要处理异常和日志// 初始化VM接口 VisionMasterAPI.Initialize(); // 加载方案文件 VisionMasterAPI.LoadSolution(D:\Projects\MyVision.sol); // 触发执行指定Group并等待完成 bool ok VisionMasterAPI.ExecuteGroup(Group_正面检测, timeout: 5000); if (ok) { // 从变量或通讯结果中读取检测结果 string result VisionMasterAPI.ReadGlobalVariable(strResult); // 根据结果控制后续动作 }注意“ExecuteGroup”这个调用默认是阻塞式的——它会等Group执行完成后才返回。这样可以非常自然地跟上位机的流程控制结合起来。如果某个Group执行时间较长可以在另一个线程中去调用避免界面卡死。SDK调用时最常见的坑是加载方案文件后如果外部修改了方案并保存运行中的SDK可能不会自动加载最新文件。所以部署时要么在每次调用前重新加载方案生产环境不推荐耗时要么约定好方案修改后要重启上位机软件才生效。7.3 通过全局变量与上位机交互在二次开发项目中我习惯把所有需要外部传入的参数、需要对外输出的结果全部定义成全局变量。比如产品型号、检测阈值、OK/NG标志、缺陷码等。上位机通过SDK读写这些变量能做到“不打开VM界面也能动态修改检测参数”的效果。这里有一个实用技巧给全局变量命名时写一个清晰的变量表文档像数据字典一样列清楚每个变量的类型、含义、取值范围、读写权限。别小看这个文档。大项目里视觉工程师、上位机工程师、PLC工程师三方协同如果没有这张表联调时基本靠吼效率极低。8. 一些值得长期坚持的Group使用习惯最后分享几个我这几年调VM项目时总结出来的小习惯看着不起眼但关键时候能救命。第一个习惯是“勤命名、勤注释”。给每个模块重命名以模块功能加序号来命名比如“匹配_定位基准点01”“测量_宽度02”。VM里模块多了之后双击看属性才是它本名的非常痛苦。在方案设计阶段就把命名规范定好后面维护的人会感谢你的。第二个习惯是“每个Group只做一件事”。如果发现一个Group里既做定位、又做测量、还做条码识别、最后还要通讯甚至控制IO一定要拆Group。单一职责的Group可复用性极高换项目时可以直接复制粘贴验收也方便。第三个习惯是“频繁保存方案文件”。VM的方案文件有时会因为异常退出而损坏尤其是现场调试过程中突然断电或者程序崩溃。我前期吃过一次大亏调了一天的方案没保存结果软件崩了全丢。从那以后我习惯改几个参数就CtrlS重要节点还会另存一个带时间戳的副本。这个方法土但确实最管用。还有一个体会不要盲目追新版本功能。有些新版本加了看起来很炫的模块但生态和稳定性不一定跟得上。如果是产线上的关键项目我通常会选择经过长时间验证的稳定版本。调试新功能可以但我会先在离线环境验证充分再上产线。以上内容基于实际项目经验分享不同版本VM的界面细节可能略有差异但核心逻辑和排错思路是通用的。如果你也在用VisionMaster做项目尤其是刚接触Group模块希望这篇笔记能帮你少走一些弯路。