visionPro的c#高级脚本
前言
本篇文章只是记录我最近解决的问题,涉及到一些c#知识点以及visionPro工具。
一、项目需求
这个视觉需求其实很简单,就是判定一个东西的有无。但是有一个问题就是检测的这个东西不是很稳定(具体来说就是物体表面有铁屑或者油污),导致简单的使用visionPro的拖拉工具并不能满足需求。
二、工具的使用
1、 CogPMAlignTool 和 CogFixtureTool : 一般都会出现在算法中,这里也不例外的使用到了,一般来说只要你的被检测物体会移动甚至大幅度的旋转都会使用到这两个工具,但是前提是得有一个好的特征点,不然模板工具 CogPMAlignTool 找不到模板,就没啥用了。而 CogFixtureTool 工具是一个定位工具,它起着一个跟随的作用,也就是相对于模板工具找到的坐标位置来变动。可以参考我上一篇有讲到 CogFixtureTool 工具的使用。
2、CogToolBlock:对于新手来说遇到很多的工具拖放,一般只会在一个界面里拖完,这样会导致界面很乱,而且如果把不同需要实现的功能工具也都放到一起,这样会让你后面维护你算法的人员十分痛苦的,最好的办法是实现某种功能的一部分工具放在一个CogToolBlock 工具里。例如我上面的两个 CogToolBlock 工具。
3、CogHistogramTool: 这是一个灰度工具,大家都知道黑白相机成像就是灰度照片,灰度的范围为0-255。那么这样图片就会有灰度的变化,所以这个工具也是我们能经常用到的工具。
把要检测的灰度区域给框起来,我这里框的是一片全白的区域,所以自然统计结果都是255;
这里框的区域有全白到全黑的灰度,这里的统计结果是将他们在区域的所有灰度值的平均、找最小值和最大值等等。
CogToolBlock 区域中心和找斑点所使用的工具
三、c#高级脚本
1. 代码片段一
脚本里的全局变量,后面会用到
#region Private Member Variables
private Cognex.VisionPro.ToolBlock.CogToolBlock mToolBlock;
System.Collections.ArrayList LabelList = new System.Collections.ArrayList();
double[] copyX = new double[3];
double[] copyY = new double[3];
#endregion
CogPMAlignTool pma1 = mToolBlock.Tools["CogPMAlignTool1"] as CogPMAlignTool;
CogPMAlignTool pma2 = mToolBlock.Tools["CogPMAlignTool2"] as CogPMAlignTool;
CogFixtureTool fix = mToolBlock.Tools["CogFixtureTool1"] as CogFixtureTool;
CogToolBlock block1 = mToolBlock.Tools["区域中心"] as CogToolBlock;
CogToolBlock block2 = mToolBlock.Tools["磁钢"] as CogToolBlock;
CogToolBlock block3 = mToolBlock.Tools["找斑点"] as CogToolBlock;
CogCreateSegmentTool segment = mToolBlock.Tools["CogCreateSegmentTool1"] as CogCreateSegmentTool;
CogBlobTool bolb1 = block3.Tools["CogBlobTool1"] as CogBlobTool;
CogBlobTool bolb2 = block3.Tools["CogBlobTool2"] as CogBlobTool;
CogBlobTool bolb3 = block3.Tools["CogBlobTool3"] as CogBlobTool;
pma1.Run();
fix.Run();
block1.Run();
block2.Run();
bool allResult = true;
bool[] results = new bool[]{
true,true,true};
double[] X = new double[3];
double[] Y = new double[3];
CogBlobTool[] blob = new CogBlobTool[]{
bolb1,bolb2,bolb3};
double length = (double) mToolBlock.Inputs["length"].Value;
mToolBlock.Outputs["Result"].Value = true;
这段代码很简单,我上一篇有讲
2. 代码片段二
if(pma1.Results.Count != 1 || pma1.RunStatus.Result != CogToolResultConstants.Accept)
{
label(450, 2500, CogColorConstants.Red, "图像模糊");
mToolBlock.Outputs["Result"].Value = false;
return false;
}
当模板找不到时直接判定false,并且return一下,不让代码往下运行,节约时间!
3.代码片段三
for(int i = 0 ; i < 3 ; i++)
{
if(pma2.Results.Count == 1 && (pma2.Results[0].GetPose().TranslationX < 2000 && i == 5))
continue;
blob[i].Run();
int count = blob[i].Results.GetBlobs().Count;
X[i] = segment.Segment.StartX = ((CogCircle) blob[i].Region).CenterX;
Y[i] = segment.Segment.StartY = ((CogCircle) blob[i].Region).CenterY;
for(int j = 0 ; j < blob[i].Results.GetBlobs().Count ; j++)
{
segment.Segment.EndX = blob[i].Results.GetBlobs()[j].CenterOfMassX;
segment.Segment.EndY = blob[i].Results.GetBlobs()[j].CenterOfMassY;
segment.Run();
label(100, i * 250 + j * 70 + 150, CogColorConstants.Green, Convert.ToInt32(segment.GetOutputSegment().Length).ToString());
if(j == 0 && segment.GetOutputSegment().Length > length)
{
X[i] = segment.Segment.StartX = ((CogCircle) blob[i].Region).CenterX = copyX[i];
Y[i] = segment.Segment.StartY = ((CogCircle) blob[i].Region).CenterY = copyY[i];
blob[i].Run();
count = blob[i].Results.GetBlobs().Count;
segment.Segment.EndX = blob[i].Results.GetBlobs()[j].CenterOfMassX;
segment.Segment.EndY = blob[i].Results.GetBlobs()[j].CenterOfMassY;
segment.Run();
label(250, i * 250 + j * 70 + 150, CogColorConstants.Green, Convert.ToInt32(segment.GetOutputSegment().Length).ToString());
if(segment.GetOutputSegment().Length > length)
{
label(400, i * 250 + j * 70 + 150, CogColorConstants.Red, Convert.ToInt32(segment.GetOutputSegment().Length).ToString());
results[i] = false;
break;
}
}
else if(j != 0 && segment.GetOutputSegment().Length > length)
{
label(100, i * 250 + j * 70 + 150, CogColorConstants.Blue, Convert.ToInt32(segment.GetOutputSegment().Length).ToString());
count--;
}
}//第二循环for
if(count != 1)
results[i] = false;
}//第一循环for
这段代码有两层for循环和很多个if,可读性稍微差了点,但是if 没有嵌套很多层,还是比较直观明了的。
1、 第一个if 是因为产品本来是要检测那个地方的斑点的,但是呢。。。结构在个别的情况下造成了遮挡,这种情况下是可以忽略那块地方的检测的,所以使用了continue ,continue 是对循环体的本次循环进行跳过。
2、这里是把 blob 工具的框选区域中心与找的斑点中心进行测量距离(CogCreateSegmentTool工具),如果小于给定的 Length 值就是正确的,但是大于的话就会进行重新框选区域,怎么来选这个区域呢 ?
/ / 我这里认为拿上一次找到的斑点找到的斑点中心作为重新框选的 blob 区域。因为这里的斑点每次的位置相差不是很大,虽然没有比正常找模板得到的框选区域精确,这里是正常情况下,但是我前面说了检测的东西表面有时不稳定的,会出现油污等干扰项,造成减低模板的精确性,甚至造成找不到的情况(这里没有考虑)!!! 故这里的操作就是为了减少误判性的。
3、有没有注意到里面几行长串代码label(),这是自定义的方法,是的!我们可以在里面编写一些自定义的方法,来美观我们的代码。
public void label(int x, int y, CogColorConstants color, string s){
CogGraphicLabel Mylabel = new CogGraphicLabel();
Mylabel.LineWidthInScreenPixels = 2;
Mylabel.SetXYText(x, y, s);
Mylabel.Color = color;
LabelList.Add(Mylabel);
}
顺便粘一下模板找不到的情况下的代码
CogPMAlignTool bPma1 = block1.Tools["CogPMAlignTool1"] as CogPMAlignTool;
CogPMAlignTool bPma2 = block1.Tools["CogPMAlignTool2"] as CogPMAlignTool;
CogPMAlignTool bPma3 = block1.Tools["CogPMAlignTool3"] as CogPMAlignTool;
CogPMAlignTool[] PMA = new CogPMAlignTool[]{
bPma1,bPma2,bPma3};
try //找不到模板会爆红
{
PMA[i].Run();
((CogCircle) blob[i].Region).CenterX = PMA[i].Results[0].GetPose().TranslationX;
((CogCircle) blob[i].Region).CenterY = PMA[i].Results[0].GetPose().TranslationY;
}
catch
{
((CogCircle) blob[i].Region).CenterX = copyX[i];
((CogCircle) blob[i].Region).CenterY = copyY[i];
}
代码片段四
for (int i = 0; i < 3; i++)
{
if(results[i] == false)
mToolBlock.Outputs["Result"].Value = false;
}
if(allResult == true)
label(250, 2500, CogColorConstants.Green, "未漏铆点");
else
label(250, 2500, CogColorConstants.Red, "漏铆点");
copyX = copyArray(X);
copyY = copyArray(Y);
copyArray 是个自定义方法来着,也是在这里复制给全局变量 copyX 和 copyY ; 全局变量在你点击运行算法时它会保存着数据,并不会每跑一遍算法它会重新置为初始值的。
public double[] copyArray(double[] doubleArray){
double[] copy = new double[doubleArray.Length];
for(int i = 0 ; i < doubleArray.Length;i++){
copy[i] = doubleArray[i];
}
return copy;
}
还需要将标签打印在图像上
public override void ModifyLastRunRecord(Cognex.VisionPro.ICogRecord lastRecord)
{
if(LabelList.Count > 0)
{
for (int i = 0; i < LabelList.Count; i++)
{
mToolBlock.AddGraphicToRunRecord((CogGraphicLabel) LabelList[i], lastRecord, "CogPMAlignTool1.OutputImage", "script");
}
}
}
#endregion
好了,这就是本次分享的内容