VisionPro脚本进阶:动态构建复杂数据结构输入输出的实战指南

张开发
2026/4/10 0:26:24 15 分钟阅读

分享文章

VisionPro脚本进阶:动态构建复杂数据结构输入输出的实战指南
1. 为什么需要动态构建复杂数据结构在VisionPro的自动化视觉检测项目中我们经常会遇到一些内置快捷方式无法满足需求的场景。比如需要传递矩阵化的坐标数据、批量处理参数或者自定义数据结构时简单的bool、double、string等基本类型就显得力不从心了。我遇到过这样一个实际案例客户需要检测PCB板上多个元件的三维坐标每个元件需要记录X/Y/Z三个维度的位置信息同时还要记录检测结果的状态。如果使用传统方法可能需要创建几十个独立的double类型变量不仅管理起来非常麻烦而且容易出错。这时候使用二维数组double[,]就能完美解决这个问题。动态构建数据结构的好处显而易见减少工具块臃肿避免创建大量单一变量提升代码可读性相关数据集中管理增强灵活性可以随时调整数据结构提高运行效率批量操作比单个操作更高效2. 准备工作理解VisionPro脚本基础在开始动态构建复杂数据结构之前我们需要先了解一些基础知识。VisionPro的脚本主要使用C#语言所以需要具备基本的C#编程能力。不过别担心即使你是C#新手跟着我的步骤也能快速上手。首先确保你的开发环境已经正确配置安装最新版VisionPro软件熟悉CogToolBlock的基本操作了解如何在工具块中添加脚本我建议在开始复杂数据结构的操作前先用简单类型练练手。比如尝试用脚本添加一个普通的double变量熟悉整个流程。这样当遇到问题时可以快速判断是基础操作的问题还是数据结构本身的问题。3. 动态创建二维数组输入输出现在让我们进入正题看看如何动态创建二维数组。二维数组特别适合存储表格型数据比如坐标点集、检测参数矩阵等。3.1 创建二维数组输出下面是一个完整的示例代码演示如何创建一个2行4列的二维数组并设置为输出public override bool GroupRun(ref string message, ref CogToolResultConstants result) { // 创建一个2行4列的二维数组 double[,] coordinateMatrix new double[2, 4]; // 给数组赋值实际项目中这里可能是从检测结果获取的数据 coordinateMatrix[0, 0] 10.5; // 第一行第一列 coordinateMatrix[0, 1] 20.3; // 第一行第二列 // 其他位置赋值类似... // 将数组添加到输出 mToolBlock.Outputs.Add(new CogToolBlockTerminal(CoordinateMatrix, coordinateMatrix)); // 运行工具块中的每个工具 foreach(ICogTool tool in mToolBlock.Tools) mToolBlock.RunTool(tool, ref message, ref result); return false; }重要提示这段代码有个关键特性需要注意 - 每次运行都会尝试添加同名的输出这会导致错误。所以在实际使用时通常有两种处理方式添加前先检查是否已存在同名输出运行一次后注释掉添加输出的代码如原始文章所示3.2 安全地添加输出更安全的做法是在添加前先检查是否已存在同名输出下面是改进后的代码public override bool GroupRun(ref string message, ref CogToolResultConstants result) { // 检查是否已存在同名输出 if(!mToolBlock.Outputs.Contains(CoordinateMatrix)) { double[,] coordinateMatrix new double[2, 4]; // 初始化数组... mToolBlock.Outputs.Add(new CogToolBlockTerminal(CoordinateMatrix, coordinateMatrix)); } // 运行其他工具... foreach(ICogTool tool in mToolBlock.Tools) mToolBlock.RunTool(tool, ref message, ref result); return false; }4. 动态移除不再需要的输出创建输出只是第一步合理管理输出的生命周期同样重要。不及时清理不再需要的输出会导致工具块越来越臃肿影响性能和可维护性。4.1 基本移除方法移除输出的代码相对简单public override bool GroupRun(ref string message, ref CogToolResultConstants result) { // 检查并移除输出 if(mToolBlock.Outputs.Contains(CoordinateMatrix)) { mToolBlock.Outputs.Remove(CoordinateMatrix); } // 运行其他工具... foreach(ICogTool tool in mToolBlock.Tools) mToolBlock.RunTool(tool, ref message, ref result); return false; }4.2 安全移除的最佳实践在实际项目中我建议采用更健壮的移除方式try { mToolBlock.Outputs.Remove(CoordinateMatrix); } catch(Exception ex) { // 记录错误但不中断流程 message $移除输出时出错{ex.Message}; // 可以选择记录日志或采取其他恢复措施 }这种带错误处理的移除方式可以避免因为意外情况导致整个流程中断。5. 处理更复杂的数据结构二维数组已经能解决很多问题但有时候我们需要处理更复杂的数据结构。比如可能需要同时存储坐标点和该点的检测状态。5.1 使用自定义类可以创建一个自定义类来封装复杂数据public class InspectionResult { public double X { get; set; } public double Y { get; set; } public bool IsDefective { get; set; } public string DefectType { get; set; } }然后在脚本中使用这个类public override bool GroupRun(ref string message, ref CogToolResultConstants result) { ListInspectionResult results new ListInspectionResult(); // 填充检测结果... if(!mToolBlock.Outputs.Contains(InspectionResults)) { mToolBlock.Outputs.Add(new CogToolBlockTerminal(InspectionResults, results)); } // 运行其他工具... return false; }5.2 使用字典处理键值对数据当数据需要按键访问时Dictionary是很好的选择Dictionarystring, double[] componentPositions new Dictionarystring, double[](); // 添加数据 componentPositions.Add(C1, new double[] {10.5, 20.3, 0.8}); componentPositions.Add(C2, new double[] {15.2, 25.7, 0.9}); if(!mToolBlock.Outputs.Contains(ComponentPositions)) { mToolBlock.Outputs.Add(new CogToolBlockTerminal(ComponentPositions, componentPositions)); }6. 性能优化与调试技巧使用动态数据结构虽然灵活但也需要注意性能问题。以下是我在实际项目中总结的几个关键点6.1 避免频繁添加/移除频繁地添加和移除输出会影响性能。建议在初始化阶段创建必要的输出运行时只更新数据不改变输出结构在确实不需要时才移除输出6.2 合理设置数组大小对于数组类数据结构预先设置合适的大小比动态调整更高效// 不好的做法先创建空数组再动态扩展 Listdouble points new Listdouble(); // 好的做法预先估计大小 double[] points new double[estimatedSize];6.3 调试技巧调试动态数据结构时可以添加临时输出帮助诊断// 输出数组维度信息用于调试 string arrayInfo $数组维度{coordinateMatrix.GetLength(0)}x{coordinateMatrix.GetLength(1)}; mToolBlock.Outputs.Add(new CogToolBlockTerminal(DebugInfo, arrayInfo));7. 实际项目中的应用案例让我分享一个真实的项目案例。客户需要检测液晶面板上的多个Mark点每个Mark点需要记录X/Y坐标亮度值对比度检测结果状态我们使用了一个二维数组存储所有Mark点的X/Y坐标一个一维数组存储亮度值另一个一维数组存储对比度值。这样组织数据后不仅工具块看起来清晰而且后续处理代码也更简洁。// 初始化数据结构 double[,] markPositions new double[markCount, 2]; // 存储X/Y坐标 double[] brightnessValues new double[markCount]; double[] contrastValues new double[markCount]; bool[] inspectionResults new bool[markCount]; // 在检测过程中填充数据 for(int i 0; i markCount; i) { // 获取检测结果并填充到数组中... } // 添加到输出 if(!mToolBlock.Outputs.Contains(MarkPositions)) { mToolBlock.Outputs.Add(new CogToolBlockTerminal(MarkPositions, markPositions)); mToolBlock.Outputs.Add(new CogToolBlockTerminal(BrightnessValues, brightnessValues)); // 其他输出类似... }这个方案成功将原先需要几十个单独变量的设计简化为几个结构化的数组大大提高了系统的可维护性。

更多文章