halcon与c#联合编程实现相机控制+图像平移缩放+日志记录+缺陷检测+路径规划

halcon与c#联合编程实现相机控制+图像平移缩放+日志记录+缺陷检测+路径规划


前言

本人近期在工作中遇到需要对某场景下利用海康相机进行图像缺陷检测与对应路径规划。通过对海康相机示例代码进行吸收与借鉴,最终实现了对海康相机的控制,并增加HSmartWindowControl控件,实现图像的实时显示与平移缩放功能;通过listview+toolstrip实现日志显示与类型(提示、警告、错误)分类;同时自行编制算法实现对缺陷的识别以及缺陷外扩矩形范围内的路径规划。
halcon与c#联合编程实现相机控制+图像平移缩放+日志记录+缺陷检测+路径规划_第1张图片


1.日志记录

代码如下(示例):

try
{
    lock(obj)
    {
        if (msg == string.Empty)
        {
            listView1.BeginUpdate();   //数据更新,UI暂时挂起,直到EndUpdate绘制控件,可以有效避免闪烁并大大提高加载速度  

            ListViewItem item1 = new ListViewItem();
            item1.Text = DateTime.Now.ToString("yyyy:MM:dd,HH:mm:ss");
            item1.SubItems.Add(msg);
            item1.ForeColor = color;
            listView1.Items.Add(item1);

            this.listView1.EndUpdate();  //结束数据处理,UI界面一次性绘制。
        }
        else
        {
            if (color == Color.Yellow)
                numYellow++;
            else if (color == Color.Red)
            {
                numRed++;
           }
            else
                numGreen++;

            string time = DateTime.Now.ToString("yyyy:MM:dd,HH:mm:ss");
            OutputItem outputItem = new OutputItem();
            outputItem.msg = msg;
            outputItem.color = color;
            outputItem.time = time;

            L_outputItem.Add(outputItem);
            if (L_outputItem.Count > 1000)
            {
                if (L_outputItem[0].color == Color.Yellow)
                    numYellow--;
                else if (L_outputItem[0].color == Color.Red)
                    numRed--;
                else
                    numGreen--;
                L_outputItem.RemoveAt(0);
            }
            UpdateCount();


            listView1.BeginUpdate();   //数据更新,UI暂时挂起,直到EndUpdate绘制控件,可以有效避免闪烁并大大提高加载速度  
            ListViewItem item1 = new ListViewItem();
            item1.Text = time;
            item1.SubItems.Add(msg);
            item1.ForeColor = color;
            listView1.Items.Add(item1);

            this.listView1.EndUpdate();  //结束数据处理,UI界面一次性绘制。

            log.SaveLog(LogType.Operate, msg);
        }
    }
}
catch (Exception ex)
{
    log.SaveError(ex);
}

halcon与c#联合编程实现相机控制+图像平移缩放+日志记录+缺陷检测+路径规划_第2张图片

2.图像平移缩放

代码如下(示例):

private void my_MouseWheel(object sender, MouseEventArgs e)
        {
            System.Drawing.Point pt = this.Location;
            int leftBorder = hSmartWindowControl1.Location.X;
            int rightBorder = hSmartWindowControl1.Location.X + hSmartWindowControl1.Size.Width;
            int topBorder = hSmartWindowControl1.Location.Y;
            int bottomBorder = hSmartWindowControl1.Location.Y + hSmartWindowControl1.Size.Height;
            if (e.X > leftBorder && e.X < rightBorder && e.Y > topBorder && e.Y < bottomBorder)
            {
                MouseEventArgs newe = new MouseEventArgs(e.Button, e.Clicks,
                                                     e.X - pt.X, e.Y - pt.Y, e.Delta);
                hSmartWindowControl1.HSmartWindowControl_MouseWheel(sender, newe);
            }
        }

halcon与c#联合编程实现相机控制+图像平移缩放+日志记录+缺陷检测+路径规划_第3张图片
halcon与c#联合编程实现相机控制+图像平移缩放+日志记录+缺陷检测+路径规划_第4张图片

3.特征识别与路径规划

代码如下(示例):


```csharp
  HObject ho_ROI_0, ho_ImageTmp, ho_Rectangle = null;
            HObject ho_ImageR, ho_ImageG, ho_ImageB, ho_ImageReduced;
            HObject ho_ImageGauss, ho_EdgeAmplitude, ho_Basins, ho_Region;
            HObject ho_RegionDilation, ho_RegionUnion, ho_ConnectedRegions;
            HObject ho_SelectedRegions, ho_Contours, ho_Contours_fit = null;
            HObject ho_Contour_fit = null, ho_Cross_tuple = null;

            // Local control variables 

            HTuple hv_Width = new HTuple(), hv_Height = new HTuple();
            HTuple hv_WindowHandle = new HTuple(), hv_ModelID = new HTuple();
            HTuple hv_Area = new HTuple(), hv_Row0 = new HTuple();
            HTuple hv_Column0 = new HTuple();
            HTuple hv_Row = new HTuple(), hv_Column = new HTuple();
            HTuple hv_Angle = new HTuple(), hv_Scale = new HTuple();
            HTuple hv_Score = new HTuple(), hv_I = new HTuple(), hv_A = new HTuple();
            HTuple hv_Row1 = new HTuple(), hv_Column1 = new HTuple();
            HTuple hv_Phi = new HTuple(), hv_Length1 = new HTuple();
            HTuple hv_Length2 = new HTuple(), hv_PointOrder = new HTuple();
            HTuple hv_Row2 = new HTuple(), hv_Column2 = new HTuple();
            HTuple hv_Radius = new HTuple(), hv_StartPhi = new HTuple();
            HTuple hv_EndPhi = new HTuple(), hv_PointOrder1 = new HTuple();
            HTuple hv_Number = new HTuple(), hv_Row_fit = new HTuple();
            HTuple hv_Col_fit = new HTuple(), hv_ZigzagPath_row = new HTuple();
            HTuple hv_ZigzagPath_column = new HTuple();
            // Initialize local and output iconic variables 
            HOperatorSet.GenEmptyObj(out ho_ROI_0);
            HOperatorSet.GenEmptyObj(out ho_ImageTmp);
            HOperatorSet.GenEmptyObj(out ho_Rectangle);
            HOperatorSet.GenEmptyObj(out ho_ImageR);
            HOperatorSet.GenEmptyObj(out ho_ImageG);
            HOperatorSet.GenEmptyObj(out ho_ImageB);
            HOperatorSet.GenEmptyObj(out ho_ImageReduced);
            HOperatorSet.GenEmptyObj(out ho_ImageGauss);
            HOperatorSet.GenEmptyObj(out ho_EdgeAmplitude);
            HOperatorSet.GenEmptyObj(out ho_Basins);
            HOperatorSet.GenEmptyObj(out ho_Region);
            HOperatorSet.GenEmptyObj(out ho_RegionDilation);
            HOperatorSet.GenEmptyObj(out ho_RegionUnion);
            HOperatorSet.GenEmptyObj(out ho_ConnectedRegions);
            HOperatorSet.GenEmptyObj(out ho_SelectedRegions);
            HOperatorSet.GenEmptyObj(out ho_Contours);
            HOperatorSet.GenEmptyObj(out ho_Contours_fit);
            HOperatorSet.GenEmptyObj(out ho_Contour_fit);
            HOperatorSet.GenEmptyObj(out ho_Cross_tuple);


            Int32 nEquivalenceNum = (int)numericUpDown_Param1.Value;
            if(nEquivalenceNum <= 0)
            {
                MessageBox.Show("路径等分点数值设置错误", "参数设置", MessageBoxButtons.OK, MessageBoxIcon.Error);
                OutputMsg("特征分析error:路径等分点数值设置错误!", Color.Red);
                return;
            }

            try
            {
                //对窗口进行模板匹配并将该区域以黑色覆盖(后面提取白色区域)
                hv_ModelID.Dispose();
                HOperatorSet.ReadShapeModel("D:/00-工作/00-工作-0中车四方所/00-项目/2021年项目/04-西安车体机器人自动化打磨/02-项目代码/01-Code/Window.shm",
                    out hv_ModelID);
                hv_Row0.Dispose();
                HOperatorSet.ReadTuple("D:/00-工作/00-工作-0中车四方所/00-项目/2021年项目/04-西安车体机器人自动化打磨/02-项目代码/01-Code/row.tup",
                    out hv_Row0);
                hv_Column0.Dispose();
                HOperatorSet.ReadTuple("D:/00-工作/00-工作-0中车四方所/00-项目/2021年项目/04-西安车体机器人自动化打磨/02-项目代码/01-Code/column.tup",
                    out hv_Column0);

                //HObject ho_Null = new HObject();
                //HTuple hv_N = new HTuple();
                //ho_Null.Dispose();
                //hv_N.Dispose();


                HOperatorSet.GenEmptyObj(out ho_Null);
                HOperatorSet.TestEqualRegion(ho_Image, ho_Null, out hv_N);
                if ((int)(new HTuple(hv_N.TupleEqual(1))) != 0)
                {
                    MessageBox.Show("图像为空", "图像采集", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }


                using (HDevDisposeHelper dh = new HDevDisposeHelper())
                {
                    hv_Row.Dispose();
                    hv_Column.Dispose();
                    hv_Angle.Dispose();
                    hv_Scale.Dispose();
                    hv_Score.Dispose();
                    HOperatorSet.FindScaledShapeModel(ho_Image, hv_ModelID, -((new HTuple(90)).TupleRad()
                        ), (new HTuple(90)).TupleRad(), 0.9, 1.1, 0.5, 0, 0.5, "least_squares",
                        0, 0.9, out hv_Row, out hv_Column, out hv_Angle, out hv_Scale, out hv_Score);
                }
                ho_ImageTmp.Dispose();
                HOperatorSet.CopyImage(ho_Image, out ho_ImageTmp);

                for (hv_I = 0; (int)hv_I <= (int)((new HTuple(hv_Score.TupleLength())) - 1); hv_I = (int)hv_I + 1)
                {
                    //重画车窗位置为黑色
                    using (HDevDisposeHelper dh = new HDevDisposeHelper())
                    {
                        ho_Rectangle.Dispose();
                        HOperatorSet.GenRectangle2(out ho_Rectangle, hv_Row.TupleSelect(hv_I), hv_Column.TupleSelect(
                            hv_I), 0, 190, 180);
                    }
                    HOperatorSet.OverpaintRegion(ho_ImageTmp, ho_Rectangle, ((new HTuple(0)).TupleConcat(
                        0)).TupleConcat(0), "fill");
                }


                //对图像进行处理获取打腻子区域
                ho_ImageR.Dispose();
                ho_ImageG.Dispose();
                ho_ImageB.Dispose();
                HOperatorSet.Decompose3(ho_ImageTmp, out ho_ImageR, out ho_ImageG, out ho_ImageB);

                HalconDisplay(m_Window, ho_ImageB, ImageHeight, ImageWidth);

                ho_ROI_0.Dispose();
                HOperatorSet.GenRectangle1(out ho_ROI_0, 195, 5, 1000, 1440);
                ho_ImageReduced.Dispose();
                HOperatorSet.ReduceDomain(ho_ImageB, ho_ROI_0, out ho_ImageReduced);

                ho_ImageGauss.Dispose();
                HOperatorSet.GaussFilter(ho_ImageReduced, out ho_ImageGauss, 11);
                ho_EdgeAmplitude.Dispose();
                HOperatorSet.SobelAmp(ho_ImageGauss, out ho_EdgeAmplitude, "sum_abs", 5);
                if (HDevWindowStack.IsOpen())
                {
                    HOperatorSet.SetDraw(HDevWindowStack.GetActive(), "margin");
                }
                ho_Basins.Dispose();
                HOperatorSet.WatershedsThreshold(ho_EdgeAmplitude, out ho_Basins, 10);

                ho_Region.Dispose();
                HOperatorSet.Threshold(ho_ImageReduced, out ho_Region, 180, 255);
                ho_RegionDilation.Dispose();
                HOperatorSet.DilationCircle(ho_Region, out ho_RegionDilation, 3.5);
                ho_RegionUnion.Dispose();
                HOperatorSet.Union1(ho_RegionDilation, out ho_RegionUnion);
                ho_ConnectedRegions.Dispose();
                HOperatorSet.Connection(ho_RegionUnion, out ho_ConnectedRegions);
                ho_SelectedRegions.Dispose();
                HOperatorSet.SelectShape(ho_ConnectedRegions, out ho_SelectedRegions, (new HTuple("area")).TupleConcat(
                    "roundness"), "and", (new HTuple(100)).TupleConcat(0.2), (new HTuple(1000000)).TupleConcat(1));
                ho_Contours.Dispose();
                HOperatorSet.GenContourRegionXld(ho_SelectedRegions, out ho_Contours, "border");
                HalconDisplay(m_Window, ho_Image, ImageHeight, ImageWidth);
                HalconDisplay(m_Window, ho_Contours, ImageHeight, ImageWidth);


                hv_A.Dispose();
                hv_A = "矩形";
                if ((int)(new HTuple(hv_A.TupleEqual("矩形"))) != 0)
                {
                    hv_Row1.Dispose(); hv_Column1.Dispose(); hv_Phi.Dispose(); hv_Length1.Dispose(); hv_Length2.Dispose(); hv_PointOrder.Dispose();
                    HOperatorSet.FitRectangle2ContourXld(ho_Contours, "tukey", -1, 0, 0, 3, 2,
                        out hv_Row1, out hv_Column1, out hv_Phi, out hv_Length1, out hv_Length2,
                        out hv_PointOrder);
                    ho_Contours_fit.Dispose();
                    HOperatorSet.GenRectangle2ContourXld(out ho_Contours_fit, hv_Row1, hv_Column1,
                        hv_Phi, hv_Length1, hv_Length2);
                }
                else
                {
                    hv_Row2.Dispose();
                    hv_Column2.Dispose();
                    hv_Radius.Dispose();
                    hv_StartPhi.Dispose();
                    hv_EndPhi.Dispose();
                    hv_PointOrder1.Dispose();
                    HOperatorSet.FitCircleContourXld(ho_Contours, "algebraic", -1, 0, 0, 3, 2,
                        out hv_Row2, out hv_Column2, out hv_Radius, out hv_StartPhi, out hv_EndPhi, out hv_PointOrder1);
                    ho_Contours_fit.Dispose();
                    HOperatorSet.GenCircleContourXld(out ho_Contours_fit, hv_Row2, hv_Column2,
                        hv_Radius, hv_StartPhi, hv_EndPhi, "positive", 1);
                }

                HOperatorSet.SetColor(m_Window, "red");
                HalconDisplay(m_Window, ho_Contours_fit, ImageHeight, ImageWidth);


                hv_Number.Dispose();
                HOperatorSet.CountObj(ho_Contours_fit, out hv_Number);
                HTuple end_val71 = hv_Number;
                HTuple step_val71 = 1;
                for (hv_I = 1; hv_I.Continue(end_val71, step_val71); hv_I = hv_I.TupleAdd(step_val71))
                {
                    ho_Contour_fit.Dispose();
                    HOperatorSet.SelectObj(ho_Contours_fit, out ho_Contour_fit, hv_I);
                    hv_Row_fit.Dispose();
                    hv_Col_fit.Dispose();
                    HOperatorSet.GetContourXld(ho_Contour_fit, out hv_Row_fit, out hv_Col_fit);
                    hv_ZigzagPath_row.Dispose(); hv_ZigzagPath_column.Dispose();
                    Gen_ZigzagPath_by_rectangle2(hv_Row_fit, hv_Col_fit, 8, out hv_ZigzagPath_row,out hv_ZigzagPath_column);

                    //“之”字型路线标记
                    ho_Cross_tuple.Dispose();
                    HOperatorSet.GenCrossContourXld(out ho_Cross_tuple, hv_ZigzagPath_row, hv_ZigzagPath_column, 10, 0.785398);
                    HOperatorSet.SetColor(m_Window, "blue");
                    HalconDisplay(m_Window, ho_Cross_tuple, ImageHeight, ImageWidth);
                    HOperatorSet.SetColor(m_Window, "red");
                }
            }

halcon与c#联合编程实现相机控制+图像平移缩放+日志记录+缺陷检测+路径规划_第5张图片

halcon与c#联合编程

总结

以上是针对该项目做的关键功能部分代码展示,比较适合新手初学者进行学习。
源码

你可能感兴趣的:(c#与halcon联合编程,c#,图像处理,算法)