news 2026/4/21 2:58:17

【VisionPro项目】胶路检测[使用CogCaliperTool工具检测弧线胶路]

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【VisionPro项目】胶路检测[使用CogCaliperTool工具检测弧线胶路]

1. 摘要

  • 检测需求:检测胶水宽度

  • 检测逻辑:

    • 如果胶水宽度在阈值范围内,OK
    • 如果胶水宽度超过阈值,NG

2. 产品图象

3. 检测流程

思路:

  1. 先对产品进行定位
  2. 提取出胶水区域
  3. 使用caliper工具,循环遍历,检测胶水宽度

工具组

高级脚本

#regionnamespace importsusingSystem;usingSystem.Collections;usingSystem.Drawing;usingSystem.IO;usingSystem.Windows.Forms;usingCognex.VisionPro;usingCognex.VisionPro.ToolBlock;usingCognex.VisionPro3D;usingCognex.VisionPro.ImageProcessing;usingCognex.VisionPro.PMAlign;usingCognex.VisionPro.CalibFix;usingCognex.VisionPro.ColorExtractor;usingCognex.VisionPro.Blob;usingCognex.VisionPro.Caliper;#endregionpublicclassCogToolBlockAdvancedScript:CogToolBlockAdvancedScriptBase{#regionPrivate Member VariablesprivateCognex.VisionPro.ToolBlock.CogToolBlockmToolBlock;System.Collections.ArrayListLabelList=newSystem.Collections.ArrayList();#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>publicoverrideboolGroupRun(refstringmessage,refCogToolResultConstantsresult){// 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//初始化工具CogImageConvertToolimageConvert=mToolBlock.Tools["CogImageConvertTool1"]asCogImageConvertTool;CogIPOneImageToolipo1=mToolBlock.Tools["CogIPOneImageTool1"]asCogIPOneImageTool;CogPMAlignToolpma1=mToolBlock.Tools["CogPMAlignTool1"]asCogPMAlignTool;CogFixtureToolfix1=mToolBlock.Tools["CogFixtureTool1"]asCogFixtureTool;CogColorExtractorToolcolorExtractor1=mToolBlock.Tools["CogColorExtractorTool1"]asCogColorExtractorTool;CogIPOneImageToolipo2=mToolBlock.Tools["CogIPOneImageTool2"]asCogIPOneImageTool;CogBlobToolblob1=mToolBlock.Tools["CogBlobTool1"]asCogBlobTool;CogCaliperToolcaliper1=mToolBlock.Tools["CogCaliperTool1"]asCogCaliperTool;//初始化InputsdoublepixPrecision=Convert.ToDouble(mToolBlock.Inputs["pixPrecision"].Value);//像素精度doublemaxWidthThreshold=Convert.ToDouble(mToolBlock.Inputs["maxWidthThreshold"].Value);//允许的卡尺最大宽度【物理距离】doubleminWidthThreshold=Convert.ToDouble(mToolBlock.Inputs["minWidthThreshold"].Value);//允许的卡尺最小宽度【物理距离】intTest=Convert.ToInt32(mToolBlock.Inputs["Test"].Value);//测试用doublestepDistance=Convert.ToDouble(mToolBlock.Inputs["stepDistance"].Value);//步长//初始化清空LabelList.Clear();//运行工具imageConvert.Run();ipo1.Run();pma1.Run();fix1.Run();colorExtractor1.Run();ipo2.Run();blob1.Run();//初始化参数boolResult=true;//胶路检测结果//OK的caliper的个数intcountOKCaliper=0;//NG的caliper的个数intcountNGCaliper=0;//获取最小卡尺宽度结果【物理距离】doubleminWidthResult=1000;//获取最大卡尺宽度结果【物理距离】doublemaxWidthResult=0;//设置Caliper的位置【只需手动设置blob区域就可以了,caliper可以跟随blob区域】CogCircularAnnulusSectioncircleSection=newCogCircularAnnulusSection();circleSection=(CogCircularAnnulusSection)blob1.Region;doublestartAngle=circleSection.AngleStart*180/Math.PI;doubleangleRange=circleSection.AngleSpan*180/Math.PI;//遍历整个Blob区域doubleR=circleSection.Radius*(1+circleSection.RadialScale)/2;for(inti=0;i<Convert.ToInt32(angleRange/stepDistance)&&i<Test;i++){//caliper1.Region.CenterX=circleSection.CenterX+R*Math.Cos((startAngle+i*stepDistance)/180*Math.PI);caliper1.Region.CenterY=circleSection.CenterY+R*Math.Sin((startAngle+i*stepDistance)/180*Math.PI);caliper1.Region.SideXLength=circleSection.Radius*(1-circleSection.RadialScale);caliper1.Region.SideYLength=5;caliper1.Region.Rotation=(startAngle+i*stepDistance)/180*Math.PI;caliper1.Run();try{if(caliper1.RunStatus.Result==CogToolResultConstants.Accept&&caliper1.Results.Count>0){//卡尺宽度大于最大值时NGif(Convert.ToDouble(caliper1.Results[0].Width*pixPrecision)>maxWidthThreshold){addText(caliper1.Region.CenterX,caliper1.Region.CenterY,"NG:"+(caliper1.Results[0].Width*pixPrecision).ToString("f1")+">"+maxWidthThreshold.ToString("f1"),CogColorConstants.Red,10);Result=false;countNGCaliper++;}//卡尺宽度小于最小值时NGelseif(Convert.ToDouble(caliper1.Results[0].Width*pixPrecision)<minWidthThreshold){addText(caliper1.Region.CenterX,caliper1.Region.CenterY,"NG:"+(caliper1.Results[0].Width*pixPrecision).ToString("f1")+"<"+minWidthThreshold.ToString("f1"),CogColorConstants.Cyan,10);Result=false;countNGCaliper++;}//OK时else{addText(caliper1.Region.CenterX,caliper1.Region.CenterY,(caliper1.Results[0].Width*pixPrecision).ToString("f1"),CogColorConstants.Green,10);countOKCaliper++;}//获取最小宽度if(caliper1.Results[0].Width*pixPrecision<minWidthResult){minWidthResult=caliper1.Results[0].Width*pixPrecision;}//获取最大宽度if(caliper1.Results[0].Width*pixPrecision>maxWidthResult){maxWidthResult=caliper1.Results[0].Width*pixPrecision;}}//卡尺未找到边缘对else{addText(caliper1.Region.CenterX,caliper1.Region.CenterY,"None",CogColorConstants.Yellow,10);Result=false;countNGCaliper++;}}//胶路超出Blob区域catch{addText(caliper1.Region.CenterX,caliper1.Region.CenterY,"Over",CogColorConstants.Orange,10);Result=false;countNGCaliper++;continue;}}intcountCaliper=(Convert.ToInt32(angleRange/stepDistance)<Test)?Convert.ToInt32(angleRange/stepDistance):Test;mToolBlock.Outputs["result"].Value=Result;//此段胶路检测结果mToolBlock.Outputs["countCaliper"].Value=countCaliper;//共检测了多少个CalipermToolBlock.Outputs["countOKCaliper"].Value=countOKCaliper;//共检测了多少个OK的CalipermToolBlock.Outputs["countNGCaliper"].Value=countNGCaliper;//共检测了多少个NG的CalipermToolBlock.Outputs["minWidthResult"].Value=minWidthResult;//检测到的最窄胶路宽度【物理距离】mToolBlock.Outputs["maxWidthResult"].Value=maxWidthResult;//检测到的最宽胶路宽度【物理距离】//显示结果if(Result){addText(circleSection.CenterX-200,circleSection.CenterY-200,""+"弧线-OK",CogColorConstants.Green,10);}else{addText(circleSection.CenterX-200,circleSection.CenterY-200,""+"弧线-NG",CogColorConstants.Red,10);}returnfalse;}publicvoidaddText(doublex,doubley,stringstr,CogColorConstantscolor,intsize){CogGraphicLabelMylabel=newCogGraphicLabel();Mylabel.SetXYText(x,y,str);Mylabel.Color=color;Mylabel.Font=newFont("黑体",size);Mylabel.SelectedSpaceName="Fixture";LabelList.Add(Mylabel);}#regionWhen 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>publicoverridevoidModifyCurrentRunRecord(Cognex.VisionPro.ICogRecordcurrentRecord){}#endregion#regionWhen 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>publicoverridevoidModifyLastRunRecord(Cognex.VisionPro.ICogRecordlastRecord){if(LabelList.Count>0){for(inti=0;i<LabelList.Count;i++){mToolBlock.AddGraphicToRunRecord((CogGraphicLabel)LabelList[i],lastRecord,"CogImageConvertTool1.InputImage","script");}}}#endregion#regionWhen the Script is Initialized/// <summary>/// Perform any initialization required by your script here/// </summary>/// <param name="host">The host tool</param>publicoverridevoidInitialize(Cognex.VisionPro.ToolGroup.CogToolGrouphost){// 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}

3.1 定位

实际场景中,胶水被涂在产品上边缘等位置。上料时,产品会有轻微的上料偏差,为了消除上料偏差,需要先对产品进行定位,然后胶水的检测区域才能跟随产品边缘位置调整

3.2 提取胶水

3.3 胶水图像预处理

3.4 胶水查找区域

3.5 卡尺检测胶水

3.5.1 CogCircularAnnulusSection区域

  • CogCircularAnnulusSection区域圆弧形的中心:由右下脚绿色圆圈示意
  • CogCircularAnnulusSection区域半径:绿色箭头示意
  • CogCircularAnnulusSection区域径向缩放:红色箭头的长度 / 绿色箭头的长度

  • CogCircularAnnulusSection区域的起始角度:x轴所在的方向就是0角度
  • CogCircularAnnulusSection区域的角度范围:从x轴顺时针,旋转至y轴的方向为“角度增加的正方向”
//设置Caliper所需要搜索的【只需手动设置blob区域就可以了,caliper可以跟随blob区域】CogCircularAnnulusSectioncircleSection=newCogCircularAnnulusSection();circleSection=(CogCircularAnnulusSection)blob1.Region;doublestartAngle=circleSection.AngleStart*180/Math.PI;//弧度值-->角度doubleangleRange=circleSection.AngleSpan*180/Math.PI;

3.5.2 CogCaliperTool的矩形区域,沿着CogBlobTool的CogCircularAnnulusSection区域移动

以CogBlobTool的区域为基准,设置CogCaliperTool的区域,使得CogCaliperTool的区域可以跟随CogBlobTool的区域移动,便于后续现场调试

卡尺区域的中心:

卡尺中心的位置:

caliper1.Region.CenterX=circleSection.CenterX+R*Math.Cos((startAngle)/180*Math.PI);caliper1.Region.CenterY=circleSection.CenterY+R*Math.Sin((startAngle)/180*Math.PI);caliper1.Region.SideXLength=circleSection.Radius*(1-circleSection.RadialScale);caliper1.Region.SideYLength=5;caliper1.Region.Rotation=(startAngle)/180*Math.PI;

CogCaliperTool矩形区域的SideXLength:

caliper1.Region.SideXLength=circleSection.Radius*(1-circleSection.RadialScale)//由下图中“绿色箭头的长度、减去红色箭头的长度”

SideXLength:如图所示的“蓝色箭头间距”

3.5.3 卡尺循环遍历逻辑

每次循环,caliper的移动方式:

caliper1.Region.CenterX=circleSection.CenterX+dbR*Math.Cos((startAngle+i*stepDistance)/180*Math.PI);caliper1.Region.CenterY=circleSection.CenterY+dbR*Math.Sin((startAngle+i*stepDistance)/180*Math.PI);caliper1.Region.SideXLength=circleSection.Radius*(1-circleSection.RadialScale);caliper1.Region.SideYLength=5;caliper1.Region.Rotation=(startAngle+i*stepDistance)/180*Math.PI;

R:如下图所示黄色箭头的长度;

doubleR=circleSection.Radius*(1+circleSection.RadialScale)/2;

卡尺的矩形区域中心点,移动的轨迹:CogCircularAnnulusSection区域中心的虚线

5. 总结

  1. 理解“CogCircularAnnulusSection区域的参数”。
  2. 理解“CogCaliperTool的矩形区域,沿着CogBlobTool的CogCircularAnnulusSection区域移动”,使得CogCaliperTool的区域可以跟随CogBlobTool的区域。实际生产中,胶水路径更加多样,会有多处弧线型胶水路径,能更好的复用此ToolBlock,减轻重复的工作量
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/21 2:58:07

校园跑腿小程序源码 _ 跑腿便利店小程序 含搭建教程

内容目录一、详细介绍二、效果展示1.部分代码2.效果图展示一、详细介绍 校园跑腿小程序源码 | 跑腿便利店小程序 本项目后端采用 midway3.0&#xff0c;后台采用 nuxt2.x,小程序采用 uniapp 实现的一套跑腿下单接单系统。 主要功能&#xff1a;跑腿、快递代取、陪练陪玩、软…

作者头像 李华
网站建设 2026/4/21 2:46:36

如何用 Chrome 的 Rendering 面板监控页面的重排频率

Chrome Rendering 面板不提供重排频率统计&#xff0c;仅能高亮重排区域和显示帧时间&#xff1b;需通过 Performance 面板录制后筛选 Layout 事件并手动计数独立块数量来获取真实重排次数。Chrome Rendering 面板里根本没“重排频率”这个指标直接说结论&#xff1a;Rendering…

作者头像 李华
网站建设 2026/4/21 2:37:30

VibeVoice实时语音合成体验:一键部署,感受300ms超低延迟的AI对话

VibeVoice实时语音合成体验&#xff1a;一键部署&#xff0c;感受300ms超低延迟的AI对话 你有没有遇到过这样的场景&#xff1a;和智能助手聊天&#xff0c;问完问题后&#xff0c;它总要沉默几秒钟&#xff0c;然后才用那种一板一眼的语调念出答案&#xff1f;那种等待的感觉…

作者头像 李华
网站建设 2026/4/21 2:30:23

010、展望:架构演化的逻辑与未来——效率、智能与硬件协同设计之路

昨天深夜调一个BERT模型部署,显存又爆了。盯着监控面板上那条陡峭的曲线,我忽然想起三年前同样的场景——那时候我们还在争论要不要上Transformer。从BERT到GPT,再到最近冒出来的Mamba,这条演化路径背后到底藏着什么逻辑?今天不聊具体代码,咱们聊聊这条路上的风景和还没修…

作者头像 李华
网站建设 2026/4/21 2:29:16

如何正确使用 React 的 useContext Hook 管理组件状态

本文详解 usecontext 配合 createcontext 实现跨组件状态共享的完整流程&#xff0c;重点解决因上下文未正确提供导致的 “setname is not a function” 报错问题&#xff0c;并给出结构清晰、可直接落地的实践方案。 本文详解 usecontext 配合 createcontext 实现跨组件状…

作者头像 李华