液体定容-相机视觉(halcon)辅助

液体定容-相机视觉辅助

定容容器应公司要求,完成上图容器自动定容的视觉部分,要求精度0.2ml。视觉处理用的halcon导出到c#,封装为接口,根据外部触发返回速度值0/1/2,即停止/慢速/快速定容。

设计思路

1,查找刻度线模板:
ho_Image.Dispose();
HOperatorSet.GrabImageAsync(out ho_Image, hv_CameraHandle, -1);
HImage hImage = new HImage();
HObject regin1 = new HObject();
HobjectToHimage(ho_Image, ref hImage);
mView.AddIconicVar(hImage);
//只在首次检测时查找刻度线模板和创建直线查找模型
if (times == 0)
{
HOperatorSet.SetSystem(“border_shape_models”, “false”);
//break;
ho_ROI_0.Dispose();
HOperatorSet.GenRectangle1(out ho_ROI_0, 800, 185.929, 1200, 688.786);
ho_TemplateImage.Dispose();
HOperatorSet.ReduceDomain(ho_Image, ho_ROI_0, out ho_TemplateImage);
ho_ModelContours.Dispose();
HOperatorSet.GetShapeModelContours(out ho_ModelContours, hv_ModelID, 1);

 //Matching 01: Find the model
 using (HDevDisposeHelper dh = new HDevDisposeHelper())
 {
     hv_Row.Dispose(); hv_Column.Dispose(); hv_Angle.Dispose(); hv_Score.Dispose();
     HOperatorSet.FindShapeModel(ho_TemplateImage, hv_ModelID, (new HTuple(-3)).TupleRad(), (new HTuple(6)).TupleRad(),
         0.7, 1, 0, "interpolation", (new HTuple(4)).TupleConcat(5), 0.9, out hv_Row, out hv_Column, out hv_Angle, out hv_Score);
 }

 //show XLD
 for (hv_I = 0; (int)hv_I <= (int)((new HTuple(hv_Score.TupleLength())) - 1); hv_I = (int)hv_I + 1)
 {
     hv_HomMat2D.Dispose();
     HOperatorSet.HomMat2dIdentity(out hv_HomMat2D);
     using (HDevDisposeHelper dh = new HDevDisposeHelper())
     {
         HTuple ExpTmpOutVar_0;
         HOperatorSet.HomMat2dRotate(hv_HomMat2D, hv_Angle.TupleSelect(hv_I), 0, 0,
             out ExpTmpOutVar_0);
         hv_HomMat2D.Dispose();
         hv_HomMat2D = ExpTmpOutVar_0;
     }
     using (HDevDisposeHelper dh = new HDevDisposeHelper())
     {
         HTuple ExpTmpOutVar_0;
         HOperatorSet.HomMat2dTranslate(hv_HomMat2D, hv_Row.TupleSelect(hv_I), hv_Column.TupleSelect(
             hv_I), out ExpTmpOutVar_0);
         hv_HomMat2D.Dispose();
         hv_HomMat2D = ExpTmpOutVar_0;
     }
     ho_TransContours.Dispose();
     HOperatorSet.AffineTransContourXld(ho_ModelContours, out ho_TransContours,
         hv_HomMat2D);

     HOperatorSet.GenEmptyObj(out regin1);
     HOperatorSet.GenRegionContourXld(ho_TransContours, out regin1, "filled");
     if (regin1 != null && regin1.IsInitialized())
     {
         mView.ChangeGraphicSettings(Mode.COLOR, "green");
         mView.AddIconicVar(regin1);
         mView.Repaint();
     }
 }
 hv_line.Dispose();
 if (hv_Score.TupleLength() >= 1 && (double)hv_Score[0] > 0.95)
 {
     using (HDevDisposeHelper dh = new HDevDisposeHelper())
     {
         hv_line = new HTuple();
         hv_line = hv_line.TupleConcat(hv_Row[0] + 420);
         hv_line = hv_line.TupleConcat(366.299);
         hv_line = hv_line.TupleConcat(hv_Row[0] + 420);
         hv_line = hv_line.TupleConcat(582.921);
     }
 }
 else
 {
     mView.AddText("首次运行未查找到定容线模板", 100, 100, 65, "red");
     mView.Repaint();
     continue;
 }
 hv_MetrologyHandle.Dispose(); hv_Index1.Dispose();
 HOperatorSet.CreateMetrologyModel(out hv_MetrologyHandle);
 HOperatorSet.AddMetrologyObjectGeneric(hv_MetrologyHandle, "line", hv_line, 410, 5, 1, 50, new HTuple(), new HTuple(), out hv_Index1);
 HOperatorSet.SetMetrologyObjectParam(hv_MetrologyHandle, "all", "measure_transition", "uniform");
 HOperatorSet.SetMetrologyObjectParam(hv_MetrologyHandle, "all", "num_measures", 20);
 HOperatorSet.SetMetrologyObjectParam(hv_MetrologyHandle, "all", "num_instances", 1);
 HOperatorSet.SetMetrologyObjectParam(hv_MetrologyHandle, "all", "measure_sigma", 5);
 HOperatorSet.SetMetrologyObjectParam(hv_MetrologyHandle, "all", "measure_interpolation", "bicubic");
 HOperatorSet.SetMetrologyObjectParam(hv_MetrologyHandle, "all", "measure_select", "last");
 HOperatorSet.SetMetrologyObjectParam(hv_MetrologyHandle, "all", "min_score", 0.5);

}
2,查找液面位置:
HOperatorSet.ApplyMetrologyModel(ho_Image, hv_MetrologyHandle);
ho_Contours.Dispose(); hv_Row1.Dispose(); hv_Column1.Dispose();
HOperatorSet.GetMetrologyObjectMeasures(out ho_Contours, hv_MetrologyHandle, 0, “all”, out hv_Row1, out hv_Column1);
HOperatorSet.GetMetrologyObjectResult(hv_MetrologyHandle, 0, “all”, “result_type”, “score”, out HTuple line_score);
mView.ChangeGraphicSettings(Mode.COLOR, “green”);
mView.AddIconicVar(regin1);
3,判断页面位置与模板位置的距离,保存图片
//判断是否找到液位线
if (line_score.Length < 1)
{
line_score.Dispose();
idd++;
if (idd > 4)
{
stop = true;
times++;
mView.AddText(“定容结束”, 100, 100, 100, “red”);
mView.Repaint();
SaveImage(“D:图片处理”, $“D:图片处理{dayNow}{timeNow}{times}”, hImage, “bmp”);
hImage = mView.DumpWindows();
//保存处理后的截图
SaveImage(“D:图片处理”, KaTeX parse error: Expected 'EOF', got '}' at position 133: … break; }? else …“定容结束{idd}次判断”, 100, 100, 100, “red”);
mView.Repaint();
Thread.Sleep(200);
}
}
else
{
idd = 0;
ho_Cross.Dispose();
HOperatorSet.GenCrossContourXld(out ho_Cross, hv_Row1, hv_Column1, 20, 0.785398);
hv_Parameter.Dispose();
HOperatorSet.GetMetrologyObjectResult(hv_MetrologyHandle, 0, 0, “result_type”, “all_param”, out hv_Parameter);
ho_Contour.Dispose();
HOperatorSet.GetMetrologyObjectResultContour(out ho_Contour, hv_MetrologyHandle, 0, 0, 1.5);
mView.AddIconicVar(ho_Contour);
mView.Repaint();
hv_diff.Dispose();

 using (HDevDisposeHelper dh = new HDevDisposeHelper())
 {
     hv_diff = (hv_Parameter.TupleSelect(0) + hv_Parameter.TupleSelect(2)) / 2 - hv_Row;
 }
 if ((hv_Parameter.TupleSelect(0) + hv_Parameter.TupleSelect(2) - 2 * hv_Row) > 500)
 {
     mView.AddText("快速定容", 100, 100, 100, "green");
 }
 else
 {
     mView.AddText("慢速定容", 100, 100, 100, "yellow");
 }
 mView.Repaint();

}
//是否存图判断,30次存一张约为7秒一图
if (times % 20 == 0)
{
//保存原图
SaveImage(“D:图片处理”, $“D:图片处理{dayNow}{timeNow}{times}”, hImage, “bmp”);
hImage = mView.DumpWindows();
//保存处理后的截图
SaveImage(“D:图片处理”, $“D:图片处理{dayNow}{timeNow}{times}”, hImage, “png”);
hImage.Dispose();
}
times++;

最终效果图

请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述