VisionPro —— 不规则胶路检测

article/2025/8/10 4:58:14

简介

本文介绍了一种基于Cognex视觉工具的胶路检测方法,分为直线和弧形两部分检测。

直线部分采用卡尺工具检测胶路宽度,通过动态调整仿射矩形区域进行多位置测量;弧形部分使用blob工具沿圆周设置检测区域。

两种方法均通过脚本实现工具映射、参数绑定和结果分析功能,支持调试模式显示检测区域和结果标注。

通过try-catch异常处理机制确保检测过程稳定,直线部分可检测断胶情况,弧形部分通过径向补偿实现圆周检测。

此方法具有参数可调性,可根据实际需求灵活配置工具组合和检测参数,适用于不同形状胶路的自动化检测需求。

效果总览

工具

使用结果分析工具输出总结果

直线部分

工具及参数

只用了最基础的模板和定位,卡尺工具是主体。

自定义参数可根据项目需求灵活配置

脚本

映射所有工具并运行,初始化所需参数并与输入参数完成绑定。

创建仿射矩形对象并配置参数,注释的部分为调试用途

调试时取消代码注释,调整步距参数,检查矩形的尺寸、位置和角度是否符合预期效果。

使用try-catch语句能够有效避免因断胶导致卡尺搜索失败时程序报错中断,从而确保后续代码和工具的正常执行。

添加了文字显示功能,采用方法重载的方式实现。通过定义两个同名方法,可以根据需要灵活选择不同的显示效果。

脚本源码

#region namespace imports
using System;
using System.Collections;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using Cognex.VisionPro;
using Cognex.VisionPro.ToolBlock;
using Cognex.VisionPro3D;
using Cognex.VisionPro.PMAlign;
using Cognex.VisionPro.CalibFix;
using Cognex.VisionPro.Caliper;
#endregionpublic class CogToolBlockAdvancedScript : CogToolBlockAdvancedScriptBase
{#region Private Member Variablesprivate Cognex.VisionPro.ToolBlock.CogToolBlock mToolBlock;private CogGraphicCollection gc = new CogGraphicCollection();#endregion/// <summary>/// Called when the parent tool is run./// Add code here to customize or replace the normal run behavior./// </summary>/// <param name="message">Sets the Message in the tool's RunStatus.</param>/// <param name="result">Sets the Result in the tool's RunStatus</param>/// <returns>True if the tool should run normally,///          False if GroupRun customizes run behavior</returns>public override bool GroupRun(ref string message, ref CogToolResultConstants result){// To let the execution stop in this script when a debugger is attached, uncomment the following lines.// #if DEBUG// if (System.Diagnostics.Debugger.IsAttached) System.Diagnostics.Debugger.Break();// #endif// Run each tool using the RunTool function// 映射工具并运行,注意这里把 foreach 运行所有工具那行代码删了CogPMAlignTool pma = mToolBlock.Tools["CogPMAlignTool1"]as CogPMAlignTool;CogFixtureTool fix = mToolBlock.Tools["CogFixtureTool1"]as CogFixtureTool;CogCaliperTool cal = mToolBlock.Tools["CogCaliperTool1"]as CogCaliperTool;gc.Clear();pma.Run();fix.Run();cal.Run();// 给输出的结果初始化为falsemToolBlock.Outputs["FlowResult"].Value = false;bool FlowResult = true;// 初始化参数并与输入参数绑定double max = 0,min = 100,Pitch = (double) mToolBlock.Inputs["Pitch"].Value,StartX = (double) mToolBlock.Inputs["StartX"].Value,StartY = (double) mToolBlock.Inputs["StartY"].Value,SearchLength = (double) mToolBlock.Inputs["SearchLength"].Value,CaliperLengthX = (double) mToolBlock.Inputs["CaliperLengthX"].Value,CaliperLengthY = (double) mToolBlock.Inputs["CaliperLengthY"].Value,CaliperRotation = (double) mToolBlock.Inputs["CaliperRotation"].Value,SearchAngle = (double) mToolBlock.Inputs["SearchAngle"].Value,scale = (double) mToolBlock.Inputs["scale"].Value;int TestCount = (int) mToolBlock.Inputs["TestCount"].Value;bool breakLine = true;if (pma.RunStatus.Result == CogToolResultConstants.Accept){for (int i = 0; i < (SearchLength / Pitch) && i < TestCount; i++){ double CaliperDegrees = CaliperRotation * Math.PI / 180;double SearchDegrees = SearchAngle * Math.PI / 180;CogRectangleAffine rect = new CogRectangleAffine();rect.Rotation = CaliperDegrees;rect.CenterX = StartX - i * Pitch * Math.Sin(SearchDegrees);rect.CenterY = StartY + i * Pitch * Math.Cos(SearchDegrees);rect.SideXLength = Convert.ToInt32(mToolBlock.Inputs["CaliperLengthX"].Value);rect.SideYLength = Convert.ToInt32(mToolBlock.Inputs["CaliperLengthY"].Value);// 测试用显示矩形位置//rect.CenterX = pma.Results[0].GetPose().TranslationX + StartX - i * Pitch * Math.Sin(SearchDegrees);//rect.CenterY = pma.Results[0].GetPose().TranslationY + StartY + i * Pitch * Math.Cos(SearchDegrees);//gc.Add(rect);//MessageBox.Show("X坐标:" + rect.CenterX.ToString() + "Y坐标:" + rect.CenterY.ToString());// 把矩形给到卡尺的搜索范围并运行卡尺工具cal.Region = rect;cal.Run();max = max < (cal.Results[0].Width * scale) ? (cal.Results[0].Width * scale) : max;min = min > (cal.Results[0].Width * scale) ? (cal.Results[0].Width * scale) : min;//MessageBox.Show(max.ToString());try {	  if(cal.RunStatus.Result == CogToolResultConstants.Accept){if(((double) (cal.Results[0].Width * scale) > (double) mToolBlock.Inputs["WidthMax"].Value)|| ((double) (cal.Results[0].Width * scale) < (double) mToolBlock.Inputs["WidthMin"].Value)){AddLabel(pma.Results[0].GetPose().TranslationX + cal.Region.CenterX, pma.Results[0].GetPose().TranslationY + cal.Region.CenterY, "" + (cal.Results[0].Width * scale).ToString("f1"), CogColorConstants.Red);FlowResult = false;}else{AddLabel(pma.Results[0].GetPose().TranslationX + cal.Region.CenterX, pma.Results[0].GetPose().TranslationY + cal.Region.CenterY, "" + (cal.Results[0].Width * scale).ToString("f1"), CogColorConstants.Green);}}}catch (Exception){breakLine = false;AddLabel(pma.Results[0].GetPose().TranslationX + cal.Region.CenterX, pma.Results[0].GetPose().TranslationY + cal.Region.CenterY, "NG", CogColorConstants.Red);// MessageBox.Show("卡尺g了");// 继续执行或终止循环, 如果需要终止检测,可添加: return false;}}}AddLabel(520, 50, breakLine ? " " : "直线部分断胶", breakLine);AddLabel(520, 100, "直线部分最小值" + min.ToString("f1"), true);AddLabel(520, 150, "直线部分最大值" + max.ToString("f1"), true);mToolBlock.Outputs["FlowResult"].Value = FlowResult;return false;}// 添加文本方法private void AddLabel (double x, double y, string text, bool b){CogGraphicLabel label = new CogGraphicLabel();label.BackgroundColor = CogColorConstants.None;label.Color = b ? CogColorConstants.Green : CogColorConstants.Red;label.Font = new Font("楷体", 20);label.SetXYText(x, y, text);gc.Add(label);}private void AddLabel (double x, double y, string text, CogColorConstants color){CogGraphicLabel label = new CogGraphicLabel();label.BackgroundColor = CogColorConstants.None;label.Color = color;label.Font = new Font("楷体", 6);label.SetXYText(x, y, text);gc.Add(label);}#region When the Current Run Record is Created/// <summary>/// Called when the current record may have changed and is being reconstructed/// </summary>/// <param name="currentRecord">/// The new currentRecord is available to be initialized or customized.</param>public override void ModifyCurrentRunRecord(Cognex.VisionPro.ICogRecord currentRecord){}#endregion#region When the Last Run Record is Createdpublic override void ModifyLastRunRecord(Cognex.VisionPro.ICogRecord lastRecord){foreach (ICogGraphic item in gc){mToolBlock.AddGraphicToRunRecord(item, lastRecord, "CogPMAlignTool1.InputImage", "");}}#endregion#region When the Script is Initialized/// <summary>/// Perform any initialization required by your script here/// </summary>/// <param name="host">The host tool</param>public override void Initialize(Cognex.VisionPro.ToolGroup.CogToolGroup host){// DO NOT REMOVE - Call the base class implementation first - DO NOT REMOVEbase.Initialize(host);// Store a local copy of the script hostthis.mToolBlock = ((Cognex.VisionPro.ToolBlock.CogToolBlock)(host));}#endregion}

圆形部分

工具及参数

同直线部分一样,blob工具是核心

同上

调试的时候同样把相应的代码打开并调小步距。

脚本

同上

脚本源码

#region namespace imports
using System;
using System.Collections;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using Cognex.VisionPro;
using Cognex.VisionPro.ToolBlock;
using Cognex.VisionPro3D;
using Cognex.VisionPro.PMAlign;
using Cognex.VisionPro.CalibFix;
using Cognex.VisionPro.Caliper;
using Cognex.VisionPro.Blob;
#endregionpublic class CogToolBlockAdvancedScript : CogToolBlockAdvancedScriptBase
{#region Private Member Variablesprivate Cognex.VisionPro.ToolBlock.CogToolBlock mToolBlock;private CogGraphicCollection gc = new CogGraphicCollection();#endregion/// <summary>/// Called when the parent tool is run./// Add code here to customize or replace the normal run behavior./// </summary>/// <param name="message">Sets the Message in the tool's RunStatus.</param>/// <param name="result">Sets the Result in the tool's RunStatus</param>/// <returns>True if the tool should run normally,///          False if GroupRun customizes run behavior</returns>public override bool GroupRun(ref string message, ref CogToolResultConstants result){// To let the execution stop in this script when a debugger is attached, uncomment the following lines.// #if DEBUG// if (System.Diagnostics.Debugger.IsAttached) System.Diagnostics.Debugger.Break();// #endif// Run each tool using the RunTool function// 映射工具并运行,注意这里把 foreach 运行所有工具那行代码删了CogPMAlignTool pma1 = mToolBlock.Tools["CogPMAlignTool1"]as CogPMAlignTool;CogFixtureTool fix1 = mToolBlock.Tools["CogFixtureTool1"]as CogFixtureTool;CogFindCircleTool cir1 = mToolBlock.Tools["CogFindCircleTool1"]as CogFindCircleTool;CogBlobTool blob1 = mToolBlock.Tools["CogBlobTool1"]as CogBlobTool;gc.Clear();pma1.Run();fix1.Run();cir1.Run();blob1.Run();// 给输出的结果初始化为falsemToolBlock.Outputs["FlowResult"].Value = false;bool FlowResult = true;// 初始化参数并与输入参数绑定double Pitch = (double) mToolBlock.Inputs["Pitch"].Value,             // 步长StartArc = (double) mToolBlock.Inputs["StartArc"].Value,       // 开始角度SearchAngle = (double) mToolBlock.Inputs["SearchAngle"].Value, // 搜索范围BlobLengthX = (double) mToolBlock.Inputs["BlobLengthX"].Value, // 矩形长BlobLengthY = (double) mToolBlock.Inputs["BlobLengthY"].Value, // 矩形宽scale = (double) mToolBlock.Inputs["scale"].Value;             // 缩放系数int TestCount = (int) mToolBlock.Inputs["TestCount"].Value,      // 循环次数限制RadiusCompensate = (int) mToolBlock.Inputs["RadiusCompensate"].Value; // 半径补偿// 主循环:生成仿射矩形并检测for (int i = 0; i < SearchAngle/Pitch && i < TestCount; i++){// 计算当前角度(度转弧度)double currentAngleDegrees = StartArc + i * Pitch;double currentAngleRadians = currentAngleDegrees * Math.PI / 180;// 创建仿射矩形(短边垂直于切线使矩形指向圆心)CogRectangleAffine rect = new CogRectangleAffine();rect.SideXLength = BlobLengthX;rect.SideYLength = BlobLengthY;rect.Rotation = currentAngleRadians;  // 短边与半径方向一致// 计算矩形中心位置rect.CenterX = cir1.Results.GetCircle().CenterX + (cir1.Results.GetCircle().Radius + RadiusCompensate) * Math.Cos(currentAngleRadians);rect.CenterY = cir1.Results.GetCircle().CenterY + (cir1.Results.GetCircle().Radius + RadiusCompensate) * Math.Sin(currentAngleRadians);blob1.Region = rect;blob1.Run();// 调试显示矩形位置//rect.CenterX = pma1.Results[0].GetPose().TranslationX + cir1.Results.GetCircle().CenterX +    //  (cir1.Results.GetCircle().Radius + RadiusCompensate) * Math.Cos(currentAngleRadians);//rect.CenterY = pma1.Results[0].GetPose().TranslationY + cir1.Results.GetCircle().CenterY +     //  (cir1.Results.GetCircle().Radius + RadiusCompensate) * Math.Sin(currentAngleRadians);//gc.Add(rect);try{if(blob1.Results.GetBlobs().Count > 0){AddLabel(pma1.Results[0].GetPose().TranslationX + rect.CenterX, pma1.Results[0].GetPose().TranslationY + rect.CenterY, "OK", true);}else{AddLabel(pma1.Results[0].GetPose().TranslationX + rect.CenterX, pma1.Results[0].GetPose().TranslationY + rect.CenterY, "NG", false);FlowResult = false;}}catch{AddLabel(pma1.Results[0].GetPose().TranslationX + cir1.Results.GetCircle().CenterX + rect.CenterX, pma1.Results[0].GetPose().TranslationY + cir1.Results.GetCircle().CenterY + rect.CenterY, "None", false);continue;}}//MessageBox.Show(angleRadians.ToString());AddLabel(520, 200, FlowResult ? " " : "圆形部分断胶", FlowResult ? CogColorConstants.Green : CogColorConstants.Red);mToolBlock.Outputs["FlowResult"].Value = FlowResult;return false;}// 添加文本方法private void AddLabel (double x, double y, string text, bool b){CogGraphicLabel label = new CogGraphicLabel();label.BackgroundColor = CogColorConstants.None;label.Color = b ? CogColorConstants.Green : CogColorConstants.Red;label.Font = new Font("楷体", 10);label.SetXYText(x, y, text);gc.Add(label);}private void AddLabel (double x, double y, string text, CogColorConstants color){CogGraphicLabel label = new CogGraphicLabel();label.BackgroundColor = CogColorConstants.None;label.Color = color;label.Font = new Font("楷体", 20);label.SetXYText(x, y, text);gc.Add(label);}#region When the Current Run Record is Created/// <summary>/// Called when the current record may have changed and is being reconstructed/// </summary>/// <param name="currentRecord">/// The new currentRecord is available to be initialized or customized.</param>public override void ModifyCurrentRunRecord(Cognex.VisionPro.ICogRecord currentRecord){}#endregion#region When the Last Run Record is Created/// <summary>/// Called when the last run record may have changed and is being reconstructed/// </summary>/// <param name="lastRecord">/// The new last run record is available to be initialized or customized.</param>public override void ModifyLastRunRecord(Cognex.VisionPro.ICogRecord lastRecord){foreach (ICogGraphic item in gc){mToolBlock.AddGraphicToRunRecord(item, lastRecord, "CogPMAlignTool1.InputImage", "");}}#endregion#region When the Script is Initialized/// <summary>/// Perform any initialization required by your script here/// </summary>/// <param name="host">The host tool</param>public override void Initialize(Cognex.VisionPro.ToolGroup.CogToolGroup host){// DO NOT REMOVE - Call the base class implementation first - DO NOT REMOVEbase.Initialize(host);// Store a local copy of the script hostthis.mToolBlock = ((Cognex.VisionPro.ToolBlock.CogToolBlock)(host));}#endregion}


http://www.hkcw.cn/article/vlNvaSmsgs.shtml

相关文章

QT中更新或添加组件时出现“”qt操作至少需要一个处于启用状态的有效资料档案库“解决方法”

在MaintenanceTool.exe中点击下一步 第一个&#xff1a; 第二个&#xff1a; 第三个&#xff1a; 以上任意一个放入资料库中

【PyQt5】从零开始的PyQt5 - QLabel篇

从零开始的PyQt5 - QLabel篇 引言一、简述二、例程2.1 显示到QWidget窗口上2.2 重新设置Label大小和对齐方式2.3 添加内容&#xff0c;设置边框2.4 显示富文本 三、参考 引言 QLabel主要用于显示文本或图像&#xff0c;不提供用户交互功能。本文主要简述PyQt5中的QLabel以及展…

Microsoft Rewards——微软免费发钱!

Microsoft Rewards 是微软推出的用于推广其搜索引擎 Bing 的一项服务&#xff0c;用户只需要使用 Bing 进行任何搜索&#xff0c;就可以获得对应积分&#xff0c;可以兑换礼品卡等奖励。 ps&#xff1a;Bing本来就是中国大陆最好的搜索引擎。 举例&#xff1a;假设将 Bing 最为…

基于python的天气可视化系统的设计与实现

博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业六年&#xff0c;熟悉各种主流语言&#xff0c;精通java、python、php、爬虫、web开发&#xff0c;已经做了六年的毕业设计程序开发&#xff0c;开发过上千套毕业设计程序&#xff0c;没有什么华丽的语言&#xff0…

设计模式——组合设计模式(结构型)

摘要 组合设计模式是一种结构型设计模式&#xff0c;用于将对象组合成树形结构以表示“部分-整体”的层次结构&#xff0c;使客户端对单个对象和组合对象具有一致的访问方式。它包含抽象组件、叶子节点和组合节点&#xff0c;具有统一处理、支持递归结构和易扩展等优点&#x…

Launcher3体系化之路

&#x1f44b; 欢迎来到Launcher 3 背景 车企对于桌面的排版布局好像没有手机那般复杂&#xff0c;但也有一定的需求。部分场景下&#xff0c;要考虑的上下文比手机要多一些&#xff0c;比如有如下的一些场景&#xff1a; 手车互联。HiCar&#xff0c;CarPlay&#xff0c;An…

pikachu通关教程- over permission

如果使用A用户的权限去操作B用户的数据&#xff0c;A的权限小于B的权限&#xff0c;如果能够成功操作&#xff0c;则称之为越权操作。 越权漏洞形成的原因是后台使用了 不合理的权限校验规则导致的。 水平越权 当我们以Lucy账号登录&#xff0c;查询个人信息时&#xff0c;会有…

刷leetcode hot100--矩阵6/1

1.螺旋矩阵【很久】6/1【感觉就是思路的搬运工&#xff0c;没完全理解】 54. 螺旋矩阵 - 力扣&#xff08;LeetCode&#xff09; 原来想 但是如果是奇数矩阵&#xff0c;遍历不到中间 解决思路&#xff1a; 用left,right,top,down标记/限定每次遍历的元素&#xff0c;每次从…

Redis最佳实践——秒杀系统设计详解

基于Redis的高并发秒杀系统设计&#xff08;十万级QPS&#xff09; 一、秒杀系统核心挑战 瞬时流量洪峰&#xff1a;100万 QPS请求冲击库存超卖风险&#xff1a;精准扣减防止超卖系统高可用性&#xff1a;99.99%服务可用性要求数据强一致性&#xff1a;库存/订单/支付状态同步…

搭建基于VsCode的ESP32的开发环境教程

一、VsCode搜索ESP-IDF插件 根据插件处搜索找到ESP-IDF并安装 安装完成 二、配置安装ESP-IDF 配置IDF 按照如下配置&#xff0c;点击安装 安装完成 三、使用案例程序 创建一个闪光灯的例子程序&#xff0c;演示程序编译下载。 选择blink例子&#xff0c;闪烁LED的程序 选…

实现RabbitMQ多节点集群搭建

目录 引言 一、环境准备 二、利用虚拟机搭建 ​ 三、镜像集群配置 四、HAProxy实现负载均衡(主用虚拟机操作) 五、测试RabbitMQ集群搭建情况 引言 在现代分布式系统中&#xff0c;消息队列&#xff08;Message Queue&#xff09;扮演着至关重要的角色,而 RabbitMQ 作为…

B站视频下载器 v1.0.4|免登录下载1080P视频

核心亮点 ✅ 无需登录下载1080P高清视频✅ 支持Windows/macOS双平台✅ 纯净无广告完全免费✅ 可单独下载视频/音频/弹幕/字幕/封面 三步极简操作 粘贴B站视频链接选择保存位置点击「开始下载」 特色功能 独立下载选项&#xff08;视频/音频/弹幕/字幕/封面&#xff09;登录…

LLM-MPC混合架构:车载大语言模型用来增强自动驾驶系统

1. 概述 2025年&#xff0c;苏黎世研究团队在RSS2025会议上正式提出「LLM-MPC混合架构」&#xff0c;标志着大语言模型&#xff08;LLM&#xff09;在自动驾驶系统中的实用化迈出关键一步。该方案旨在解决传统深度学习模型在极端交通场景中泛化能力不足的问题。通过在车载终端…

leetcode-hot-100 (矩阵)

1、矩阵置零 题目链接&#xff1a;矩阵置零 题目描述&#xff1a;给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 解答 方法一&#xff1a;使用一个二维数组 这是我看到这道题目的第一个想法&am…

黑马Java面试笔记之Redis篇(分布式锁)

面试题 我看你做的项目中&#xff0c;都用到了redis&#xff0c;你在最近的项目中那些场景使用了redis呢 如果回答了分布式锁&#xff0c;那么就会有以下这个问题 redis分布式锁&#xff0c;是如何实现的&#xff1f; 需要结合项目中的业务进行回答&#xff0c;通常情况下&…

建筑兔零基础python自学记录102|Beautiful Soup库(1)-15

1、安装Beautiful Soup 2、使用测试网页获取源代码 This is a python demo page a)法1&#xff1a;直接网页右键获取 b)法2&#xff1a;request库 import requests rrequests.get(https://python123.io/ws/demo.html) print(r.text) 3、使用Beautiful Soup库 同样解析出了源…

【Java学习笔记】枚举

枚举(enum) 一、基本介绍 引出关键字&#xff1a;enum&#xff0c;全称为enumerate 枚举是一组常量集合 理解&#xff1a;枚举属于一种特殊的类&#xff0c;里面只包含一组有限的特定的对象 二、使用场景 当一个类的属性有限定条件时&#xff08;例如一个星期只能有七天&…

FFmpeg学习笔记

1. 播放器的架构 2. 播放器的渲染流程 3. ffmpeg下载与安装 3.0 查看PC是否已经安装了ffmpeg ffmpeg 3.1 下载 wget https://ffmpeg.org/releases/ffmpeg-7.0.tar.gz 3.2 解压 tar zxvf ffmpeg-7.0.tar.gz && cd ./ffmpeg-7.0 3.3 查看配置文件 ./configure …

buuctf-web

[极客大挑战 2019]Havefun 控制台检查代码修改url [极客大挑战 2019]EasySQL 密码输入 出现 sql输入错误 判断为 单引号注入 [ACTF2020 新生赛]Include 点击提示出现?file说明是文件包含问题 构造url filephp://filter/readconvert.base64-encode/resourceflag.php php:…

SAR ADC 异步逻辑设计

SAR ADC的逻辑是重要的一个模块&#xff0c;可以分为同步逻辑和异步逻辑&#xff0c;对于低速SAR ADC&#xff0c;一般采用同步逻辑&#xff0c;对于高速SAR ADC&#xff0c;一般采用异步逻辑。 这里讲一下异步逻辑的设计&#xff0c;异步逻辑一般不需要外部时钟&#xff08;当…