1. 摘要检测需求检测胶水宽度检测逻辑如果胶水宽度在阈值范围内OK如果胶水宽度超过阈值NG2. 产品图象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.ArrayListLabelListnewSystem.Collections.ArrayList();#endregion/// summary/// Called when the parent tool is run./// Add code here to customize or replace the normal run behavior./// /summary/// param namemessageSets the Message in the tools RunStatus./param/// param nameresultSets the Result in the tools RunStatus/param/// returnsTrue if the tool should run normally,/// False if GroupRun customizes run behavior/returnspublicoverrideboolGroupRun(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//初始化工具CogImageConvertToolimageConvertmToolBlock.Tools[CogImageConvertTool1]asCogImageConvertTool;CogIPOneImageToolipo1mToolBlock.Tools[CogIPOneImageTool1]asCogIPOneImageTool;CogPMAlignToolpma1mToolBlock.Tools[CogPMAlignTool1]asCogPMAlignTool;CogFixtureToolfix1mToolBlock.Tools[CogFixtureTool1]asCogFixtureTool;CogColorExtractorToolcolorExtractor1mToolBlock.Tools[CogColorExtractorTool1]asCogColorExtractorTool;CogIPOneImageToolipo2mToolBlock.Tools[CogIPOneImageTool2]asCogIPOneImageTool;CogBlobToolblob1mToolBlock.Tools[CogBlobTool1]asCogBlobTool;CogCaliperToolcaliper1mToolBlock.Tools[CogCaliperTool1]asCogCaliperTool;//初始化InputsdoublepixPrecisionConvert.ToDouble(mToolBlock.Inputs[pixPrecision].Value);//像素精度doublemaxWidthThresholdConvert.ToDouble(mToolBlock.Inputs[maxWidthThreshold].Value);//允许的卡尺最大宽度【物理距离】doubleminWidthThresholdConvert.ToDouble(mToolBlock.Inputs[minWidthThreshold].Value);//允许的卡尺最小宽度【物理距离】intTestConvert.ToInt32(mToolBlock.Inputs[Test].Value);//测试用doublestepDistanceConvert.ToDouble(mToolBlock.Inputs[stepDistance].Value);//步长//初始化清空LabelList.Clear();//运行工具imageConvert.Run();ipo1.Run();pma1.Run();fix1.Run();colorExtractor1.Run();ipo2.Run();blob1.Run();//初始化参数boolResulttrue;//胶路检测结果//OK的caliper的个数intcountOKCaliper0;//NG的caliper的个数intcountNGCaliper0;//获取最小卡尺宽度结果【物理距离】doubleminWidthResult1000;//获取最大卡尺宽度结果【物理距离】doublemaxWidthResult0;//设置Caliper的位置【只需手动设置blob区域就可以了caliper可以跟随blob区域】CogCircularAnnulusSectioncircleSectionnewCogCircularAnnulusSection();circleSection(CogCircularAnnulusSection)blob1.Region;doublestartAnglecircleSection.AngleStart*180/Math.PI;doubleangleRangecircleSection.AngleSpan*180/Math.PI;//遍历整个Blob区域doubleRcircleSection.Radius*(1circleSection.RadialScale)/2;for(inti0;iConvert.ToInt32(angleRange/stepDistance)iTest;i){//caliper1.Region.CenterXcircleSection.CenterXR*Math.Cos((startAnglei*stepDistance)/180*Math.PI);caliper1.Region.CenterYcircleSection.CenterYR*Math.Sin((startAnglei*stepDistance)/180*Math.PI);caliper1.Region.SideXLengthcircleSection.Radius*(1-circleSection.RadialScale);caliper1.Region.SideYLength5;caliper1.Region.Rotation(startAnglei*stepDistance)/180*Math.PI;caliper1.Run();try{if(caliper1.RunStatus.ResultCogToolResultConstants.Acceptcaliper1.Results.Count0){//卡尺宽度大于最大值时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);Resultfalse;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);Resultfalse;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*pixPrecisionminWidthResult){minWidthResultcaliper1.Results[0].Width*pixPrecision;}//获取最大宽度if(caliper1.Results[0].Width*pixPrecisionmaxWidthResult){maxWidthResultcaliper1.Results[0].Width*pixPrecision;}}//卡尺未找到边缘对else{addText(caliper1.Region.CenterX,caliper1.Region.CenterY,None,CogColorConstants.Yellow,10);Resultfalse;countNGCaliper;}}//胶路超出Blob区域catch{addText(caliper1.Region.CenterX,caliper1.Region.CenterY,Over,CogColorConstants.Orange,10);Resultfalse;countNGCaliper;continue;}}intcountCaliper(Convert.ToInt32(angleRange/stepDistance)Test)?Convert.ToInt32(angleRange/stepDistance):Test;mToolBlock.Outputs[result].ValueResult;//此段胶路检测结果mToolBlock.Outputs[countCaliper].ValuecountCaliper;//共检测了多少个CalipermToolBlock.Outputs[countOKCaliper].ValuecountOKCaliper;//共检测了多少个OK的CalipermToolBlock.Outputs[countNGCaliper].ValuecountNGCaliper;//共检测了多少个NG的CalipermToolBlock.Outputs[minWidthResult].ValueminWidthResult;//检测到的最窄胶路宽度【物理距离】mToolBlock.Outputs[maxWidthResult].ValuemaxWidthResult;//检测到的最宽胶路宽度【物理距离】//显示结果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){CogGraphicLabelMylabelnewCogGraphicLabel();Mylabel.SetXYText(x,y,str);Mylabel.Colorcolor;Mylabel.FontnewFont(黑体,size);Mylabel.SelectedSpaceNameFixture;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 namecurrentRecord/// The new currentRecord is available to be initialized or customized./parampublicoverridevoidModifyCurrentRunRecord(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 namelastRecord/// The new last run record is available to be initialized or customized./parampublicoverridevoidModifyLastRunRecord(Cognex.VisionPro.ICogRecordlastRecord){if(LabelList.Count0){for(inti0;iLabelList.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 namehostThe host tool/parampublicoverridevoidInitialize(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区域】CogCircularAnnulusSectioncircleSectionnewCogCircularAnnulusSection();circleSection(CogCircularAnnulusSection)blob1.Region;doublestartAnglecircleSection.AngleStart*180/Math.PI;//弧度值--角度doubleangleRangecircleSection.AngleSpan*180/Math.PI;3.5.2 CogCaliperTool的矩形区域沿着CogBlobTool的CogCircularAnnulusSection区域移动以CogBlobTool的区域为基准设置CogCaliperTool的区域使得CogCaliperTool的区域可以跟随CogBlobTool的区域移动便于后续现场调试卡尺区域的中心卡尺中心的位置caliper1.Region.CenterXcircleSection.CenterXR*Math.Cos((startAngle)/180*Math.PI);caliper1.Region.CenterYcircleSection.CenterYR*Math.Sin((startAngle)/180*Math.PI);caliper1.Region.SideXLengthcircleSection.Radius*(1-circleSection.RadialScale);caliper1.Region.SideYLength5;caliper1.Region.Rotation(startAngle)/180*Math.PI;CogCaliperTool矩形区域的SideXLengthcaliper1.Region.SideXLengthcircleSection.Radius*(1-circleSection.RadialScale)//由下图中“绿色箭头的长度、减去红色箭头的长度”SideXLength如图所示的“蓝色箭头间距”3.5.3 卡尺循环遍历逻辑每次循环caliper的移动方式caliper1.Region.CenterXcircleSection.CenterXdbR*Math.Cos((startAnglei*stepDistance)/180*Math.PI);caliper1.Region.CenterYcircleSection.CenterYdbR*Math.Sin((startAnglei*stepDistance)/180*Math.PI);caliper1.Region.SideXLengthcircleSection.Radius*(1-circleSection.RadialScale);caliper1.Region.SideYLength5;caliper1.Region.Rotation(startAnglei*stepDistance)/180*Math.PI;R如下图所示黄色箭头的长度doubleRcircleSection.Radius*(1circleSection.RadialScale)/2;卡尺的矩形区域中心点移动的轨迹CogCircularAnnulusSection区域中心的虚线5. 总结理解“CogCircularAnnulusSection区域的参数”。理解“CogCaliperTool的矩形区域沿着CogBlobTool的CogCircularAnnulusSection区域移动”使得CogCaliperTool的区域可以跟随CogBlobTool的区域。实际生产中胶水路径更加多样会有多处弧线型胶水路径能更好的复用此ToolBlock减轻重复的工作量