一、脚本的导入命名空间
点开以后显示的页面是这样的,接着就导入你想要的吧!
点击确认后,不要忘记点击箭头(向工具写入脚本)
二、开始写代码吧
- 导入自己用到的工具,方便自己以后 Run() 它们。
CogPMAlignTool PM = mToolBlock.Tools["CogPMAlignTool1"] as CogPMAlignTool;
CogFixtureTool fix = mToolBlock.Tools["CogFixtureTool1"] as CogFixtureTool;
CogFixtureTool fix1 = mToolBlock.Tools["CogFixtureTool2"] as CogFixtureTool;
CogIPOneImageTool ipo = mToolBlock.Tools["CogIPOneImageTool1"] as CogIPOneImageTool;
- 导入变量:导入自己需要用的变量,方便使用(变量可以方便我们做数据的调整,以便找到最适合的数值范围!)
bool bTrue = (bool) mToolBlock.Inputs["bTrue"].Value;
double dMean = (double) mToolBlock.Inputs["dMean"].Value;
double dVariance = (double) mToolBlock.Inputs["dVariance"].Value;
- 关于使用数组来存工具,方便后面的循环使用
CogHistogramTool[] His = new CogHistogramTool[]{his1, his2, his3, his4};
CogBlobTool[] Blob = new CogBlobTool[]{blob1, blob2, blob3, blob4};
- 合理使用return,能优化运行时间
if(PM.Results.Count != 8)
{
mToolBlock.Outputs["FlowResult"].Value = bTrue ? true : false;
return false;
}
对于当符合某一个条件就能判断结果时,使用return,可以直接不运行后面的代码,节省很多时间。
- 定义全局属性
#region Private Member Variables
private Cognex.VisionPro.ToolBlock.CogToolBlock mToolBlock;
在这里可以写一些全局要用到的常量或变量,下面是定义了用来保存标签的集合,下面会贴出使用的代码!(两个都可以)
System.Collections.ArrayList LabelList = new System.Collections.ArrayList();
// CogGraphicCollection LabelList = new CogGraphicCollection();
代码片段一解释
for(int i = 0; (i < 8 && i < (int) mToolBlock.Inputs["test"].Value); i++)
{
fix.RunParams.UnfixturedFromFixturedTransform = PM.Results[i].GetPose();
fix.Run();
his1.Run();
his2.Run();
- 这里的 Inputs[“test”] 就是我们上面所讲的导入变量 方便调试,因为这里用到了循环,如果我们需要调试时,可以选择输入 test 的值然后在哪一次循环停下来,看看是在哪里出了问题。
- **.Run()**可以让我们使某一个工具运行起来。
- 另一行代码相当在工具里将 PM.Results[0].GetPose() 与fix.RunParams.UnfixturedFromFixturedTransform 连起来。只不过,这里的模板工具的结果这里有8个,所以用代码实现CogFixtureTool工具的坐标系位置空间(X、Y轴及角度 空间坐标系)。
代码片段二解释
接上面的第一个for 循环
double dx = 0;
double dy = 0;
for(int j = 0 ; j < His.Length ; j++){
CogGraphicLabel Mylabe = new CogGraphicLabel();
CogTransform2DLinear newTrans = PM.Results[i].GetPose();
CogRectangleAffine rect = His[j].Region as CogRectangleAffine;
rect1 = rect.MapLinear(newTrans, CogCopyShapeConstants.GeometryOnly);
//rect1 = rect.MapLinear((CogTransform2DLinear)fix1.OutputImage.PixelFromRootTransform, CogCopyShapeConstants.All);
rect1.Color = CogColorConstants.Orange;
LabelList.Add(rect1);
newTrans.MapPoint(rect.CenterX, rect.CenterY, out dx, out dy);
- 这里也用到了 for 循环,His[j] 由于该算法用了四个CogHistogramTool工具,刚好使用数组运用到循环上去。
- new CogGraphicLabel(),可以自定义图像标签,并且添加到前面的全局变量LabelList --> LabelList.Add(rect1) 上去
- newTrans 是2D 线条转换区域;newTrans.MapPoint–>一般使用 Map 开头大多是复制或者映射输出。这里将 rect.CenterX 的坐标复制给 dx 。
- rect.MapLinear 是指将 newTrans 区域的东西复制过来(角度啊、边长啊,中心啊等等),且有多种模式!
注:第一个参数 CogTransform2DLinear类型 要和工具所选空间名称对比一下,一不一致都无所谓但要注意转换成自己想要的效果。
比如:
不一致时,可以将第二个参数设置为 CogCopyShapeConstants.GeometryOnly(只复制几何形状,而不复制坐标)
一致时,可以设置为 CogCopyShapeConstants.All(全部复制,包含坐标点,角度等)。
-
His[j].Region 指的是CogHistogramTool 工具的所使用的区域形状
代码片段三解释
接上面的第二个for循环,相信这段很多都能看懂,都是一些基本的判断语句。
if(His[j].Result.Mean > dMean){
Mylabe.SetXYText(dx, dy, "OK");
Mylabe.Color = CogColorConstants.Green;
LabelList.Add(Mylabe);
}else{
rect1.Color = CogColorConstants.Blue;
fix1.InputImage = PM.InputImage;
fix1.RunParams.UnfixturedFromFixturedTransform = PM.Results[i].GetPose();
fix1.Run();
Blob[j].InputImage = fix1.OutputImage;
blobAffine = rect.MapLinear(newTrans, CogCopyShapeConstants.GeometryOnly);
blobAffine.Color = CogColorConstants.Blue;
blobAffine.SetOriginCornerXCornerY(rect.CornerOriginX, rect.CornerOriginY, rect.CornerXX, rect.CornerXY, rect.CornerYX, rect.CornerYY);
blobAffine.SideXLength *= 10;
Blob[j].Region = blobAffine;
Caliper[j].Region = blobAffine;
Blob[j].Run();
Caliper[j].Run();
if(Caliper[j].Results[0].Width > 50 && Caliper[j].Results[0].Width < 75){
Mylabe.SetXYText(dx, dy, "OK");
Mylabe.Color = CogColorConstants.Green;
LabelList.Add(Mylabe);
}else{
mToolBlock.Outputs["FlowResult"].Value = bTrue ? true : false;
Mylabe.SetXYText(dx, dy, "NG");
Mylabe.Color = CogColorConstants.Red;
LabelList.Add(Mylabe);
}
Blob[j].InputImage = null; //后面会注释掉
Caliper[j].InputImage = null; //后面会注释掉
Blob[j].Run(); //后面会注释掉
Caliper[j].Run(); //后面会注释掉
}//大if
}//for循环
}//大for循环
-
fix1.InputImage = PM.InputImage 以及 Blob[j].InputImage = fix1.OutputImage 关于这几段是因为优化代码,节省运行时间,由于这是一个 if…else 语句。而且正常情况下( His[j].Result.Mean > dMean )这个条件都基本成立,那么大部分时候不需要用到工具都不用去运行处理,然而情况是只要你点击 CogToolBlock 的运行时,
所有的工具都会运行(经过下面的验证结论,是所有代码里执行了.Run() 的工具都会运行),而且工具都会保留上次的运行时的输入图片及最后一次的输入图片。
和代码 fix1.RunParams.UnfixturedFromFixturedTransform = PM.Results[i].GetPose( ) 差不多的意思,结合下面的图片你就能大概懂我讲的什么了。
这是正常情况下的工具链接状态
这是用代码( fix1.InputImage = PM.InputImage )实现的工具链接状态
这里的 Blob 工具爆红是因为,在循环过后执行了 Blob[j].InputImage = null 将 Blob 工具的输入图片给置 null 了。
当然单纯的将 InputImage 还是不行,因为还有最后一次的 InputImage 即 LastRun.InputImage ,这里还是会有图,导致Blob 工具执行。在没图和有图的情况下执行 Blob 工具区别还是有差别的,虽然相差不大,但是重要的是代码的优化思想,时刻要有一个想优化的心。所以在将 Blob置为 null 时 (Blob[j].InputImage = null),要运行一次 Blob[j].Run() ,为什么 Run() 呢 ?因为当 Blob[j].InputImage = null 时,你运行 Blob 工具时就会爆红(你可以注释掉 Blob[j].Run() ,再运行CogToolBlock,再进去Blob工具里面手动运行一下,再出来看看Blob工具是不是变成爆红了),相当于在不用Blob工具时爆红废弃,用时再运行 Blob[j].InputImage = fix1.OutputImage。(划线的都是多余的)
注: 这里的 Blob[j].Run() 是最后一句的而不是前面的那一句。
然而,就在我以为我想的不错时,执行代码验证却出乎我的预料,事实上证明,我的某些结论是错的,Blob 的 LastRun.InputImage 并不会自己运行,只有你在代码上执行了 .Run()方法 时或者是 Blob[j].InputImage 有图不为 null 时才会执行。
(这是先执行了一个NG错的产品时 ,Blob 和 Caliper 工具时的运行时间结果)
(这是执行 NG 产品后紧接执行 OK 产品 时,Blob 和 Caliper 工具时的运行时间结果,结果和上面的一模一样,证明什么?证明了这个工具没运行,即使是一模一样的图片也会有一些时间差,因为算法不可能稳定到运行两个一样的图片所用的运算时间都保持一样,如果不信可以再看下面的验证!)
(这里执行了一个NG错的产品 ,别问我为什么。因为如果我上面的结论正确时,你拿一个不走 else 代码的 OK 产品,blob工具是没法验证一样的图片算法所用的运算时间不一致,因为它根本不运行blob工具,即 blob .Run())
验证步骤: 选择一个NG产品图 --> 然后在 CogToolBlock 里运行
第一次运行结果:
第二次运行结果:
结论一: 两次结果不一样,说明算法运算两个一样的图时,运算时间也会有所差别。
结论二:Blob 的 LastRun.InputImage 并不会自己运行,只有你在代码上执行了 .Run()方法 或者是 Blob[j].InputImage 有图不为 null 时才会执行。 故:直接在将最后面的 Blob[j].Run() 和 Caliper[j].Run() 注释掉不需要了。
-
变量 blobAffine ,定义变量 blobAffine是为了给 Blob 工具 Blob[j].Region 及 Caliper[j].Region 设置区域,为了不让它跑的太偏(因为可能模板匹配找的会有一些偏差),给它设置原点,边长等。而且 CogRectangleAffine 类里面的原点属性不能直接赋值,要用方法 SetOriginCornerXCornerY()
这里设置原点,是因为开始写的时候,不是很懂定位空间,本来定位空间就可以搞定,不需要代码实现 。。。不过,既然这个方法存在应该就会有它的意义,现在还没有什么实际遇到过只能代码实现的情况。 -
虽然说上面的Blob[j].Run() 多余,那么 Blob[j].InputImage = null 多余嘛,验证如下:
(这是先执行了一个NG错的产品时 ,再运行一个OK产品时,OK产品运算的运行时间,并且不要注释了 Blob[j].InputImage = null 这句代码)
接着再次运行同样的OK产品,发现 Blob 工具的运行时间没有什么变化,但是你手动进去运行,时间确是变化着的,证明工具没有运行
(再次先执行了一个NG错的产品时 ,但是这次注释了 Blob[j].InputImage = null 这句代码,NG产品 Blob 运算的运行时间如下图)
再切换运行一个OK产品,发现 OK 产品 Blob 运算的运行时间和上面一致,并没有变化
结论:有没有 Blob[j].InputImage = null 这句代码执行时间都一样,证明在工具中,不管你有没有 xxx . InputImage ,只要你不在代码里执行 xxx . Run() 或者 你手动点击工具 xxx 都不会自己运行,从而影响代码执行时间。
三、CogFixtureTool工具的介绍
CogFixtureTool是重新定义一个自己的坐标系,重新定义原点等的定位工具。工具,界面如下:
首先,需要了解,最开始的图像的原始原点是左上角,也是最开始的坐标系空间,如下图所示:
一般来说,使用模板匹配工具 CogPMAlignTool 时就会用到 CogFixtureTool 工具。并且一般,将 CogPMAlignTool 的结果中心原点赋给 CogFixtureTool 当作新的坐标系原点。下图没有使用线链接起来,是因为使用代码 fix.RunParams.UnfixturedFromFixturedTransform = PM.Results[i].GetPose() 实现了。
链接以后,CogPMAlignTool 的中心原点就是下图新的坐标系原点。
这时候,后面使用的工具就可以使用新的空间坐标系了,比如这里面使用了 “@\Fixture”
可能很多人还是很模糊,这有什么用?下面画示意图,演示一下。
- 输入图像是这样的,目的是找到产品的污点多不多。
- 第一步就是先通过模板匹配找到产品,并且标记中心原点为模板的某处,这样每次模板匹配到的产品的中心原点都固定在产品的右上方,且x,y方向相对找到的模板方向相对不变。
- 通过 CogFixtureTool 工具建立以模板匹配中心原点,x,y,旋转角度的新坐标空间。
- 使用CogHistogramTool 工具检测污点,并且设置使用空间名称为新坐标空间的空间名称。比如图示的 CogHistogramTool 工具原点位置相对于新坐标空间原点为x=-113.69;y=70;旋转为90度。
- 这样,不管产品如何移动, CogHistogramTool 工具原点位置相对于新坐标空间原点都为x=-113.69;y=70;旋转为90度。跟随新坐标空间原点(即模板匹配结果的中心原点)结果走。
注意一点,UnfixturedSpace 与 fixturedSpace 的区别。
当使用 fixturedSpace 时,链接到的 CogFixtureTool 的 outputImage 工具的 使用空间名称 “输入图像空间” 和 “@\Fixture” 是一致的。文章来源:https://www.toymoban.com/news/detail-496602.html
当使用 UnfixturedSpace 时,链接到的 CogFixtureTool 的 outputImage 工具的 使用空间名称 “输入图像空间” 和 “@\Fixture” 是不一致的。这里的**“输入图像空间”** 则是传入 CogFixtureTool 图像的空间。文章来源地址https://www.toymoban.com/news/detail-496602.html
到了这里,关于记录编写visionPro的c#高级脚本的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!