halcon联合C#模版匹配

1. 软件运行效果演示

halcon联合C#模板匹配软件(图片自适应显示缩放移动)

2. 软件界面

85fde426934a409a94f1e1145be034bf.png

2.1 绘制ROI区域

e16c750f750f4093b708d22c627bb5d9.png

2.2 模板区域

2da084316db841ee9f6e24a93e927434.png

2.3 模板匹配参数设置

9a74e2289c264b67a7da367b4b42feb3.png

2.4 模板匹配识别

50dc387174a64ec6a76308f67cbcb314.png

2.5 日志

 4634707704de4e36a650eebbbee299c0.png

3. 程序编写

3.1 图像的自适应显示

关键算子:dev_setpart算子,可以查看halcon官方的帮助文档,对于后面的图像的缩小和放大很重要

 private void btn_readimage_Click(object sender, EventArgs e)
        {
            try
            {
                HOperatorSet.ClearWindow(hWindowControl1.HalconWindow);
                double rateimage, ratewin;
                double row1, column1, row2, column2;
                HTuple imagewidth, imageheigth, partwidth, partheigth;
                HOperatorSet.GenEmptyObj(out ho_Image);
                HOperatorSet.ReadImage(out ho_Image, "C:/Users/Public/Documents/MVTec/HALCON-17.12-Progress/examples/images/board/board-01.png");
                HOperatorSet.GetImageSize(ho_Image, out imagewidth, out imageheigth);
                HTuple Row0, Column0, Row00, Column00, Ht, Wt, r1, c1, r2, c2;

                //读取显示控件尺寸
                partwidth = hWindowControl1.Width;
                partheigth = hWindowControl1.Height;
                //显示控件尺寸
                textBox1.Text = partwidth.ToString();
                textBox2.Text = partheigth.ToString();
                //显示图像尺寸
                textBox3.Text = imagewidth.ToString();
                textBox4.Text = imageheigth.ToString();
                //计算图像比率和窗体比例
                rateimage = 1.0 * imagewidth / imageheigth;
                ratewin = 1.0 * partwidth / partheigth;
                //自适应显示图像
                if (rateimage <= ratewin)
                {
                    row1 = 0;
                    column1 = -(1.0 * imageheigth / partheigth * partwidth - imagewidth) * 1.0 / 2;
                    row2 = row1 + imageheigth;
                    column2 = column1 + 1.0 * partwidth * imageheigth / partheigth;
                    HOperatorSet.SetPart(hWindowControl1.HalconWindow, row1, column1, row2, column2);
                    HOperatorSet.DispObj(ho_Image, hWindowControl1.HalconWindow);

                    textBox5.Text = row1.ToString();
                    textBox6.Text = column1.ToString();
                    textBox7.Text = row2.ToString();
                    textBox8.Text = column2.ToString();

                    HOperatorSet.GetPart(hWindowControl1.HalconWindow, out Row0, out Column0, out Row00, out Column00);
                    textBox8.Text = Column0.ToString();
                    //图片显示成功标志
                    readimage_flag = 1;
                }
            }
            catch (Exception)
            {
                MessageBox.Show("图像加载错误");
            }


            }

3.2 图像的放大缩小

使用get_mposition算子获取鼠标在hwindowcontrol控件上的位置,以该位置为放大缩小中心,滚轮向前滑动,图像依次放大1.5倍;滚轮向后滑动,图像依次缩小0.5倍,通过setpart函数实现图像的放大和缩小。

private void hWindowControl2_HMouseWheel(object sender, HMouseEventArgs e)
        {
            try
            {
                if (readimage_flag1 == 1)
                {
                    HTuple Zoom, Row, Col, Button;
                    HTuple Row0, Column0, Row00, Column00, Ht, Wt, r1, c1, r2, c2;
                    if (e.Delta > 0)
                    {
                        Zoom = 1.5;
                    }
                    else
                    {
                        Zoom = 0.5;
                    }

                    //获取鼠标点位置
                    HOperatorSet.GetMposition(hWindowControl2.HalconWindow, out Row, out Col, out Button);
                    //获取显示窗口位置
                    HOperatorSet.GetPart(hWindowControl2.HalconWindow, out Row0, out Column0, out Row00, out Column00);
                    //获得窗体宽度和长度
                    Ht = Row00 - Row0;
                    Wt = Column00 - Column0;
                    //实现图像放大和缩小
                    if (Ht * Wt < 32000 * 32000 || Zoom == 1.5)//普通版halcon能处理的图像最大尺寸是32K*32K。如果无限缩小原图像,导致显示的图像超出限制,则会造成程序崩溃
                    {
                        r1 = (Row0 + ((1 - (1.0 / Zoom)) * (Row - Row0)));
                        c1 = (Column0 + ((1 - (1.0 / Zoom)) * (Col - Column0)));
                        r2 = r1 + (Ht / Zoom);
                        c2 = c1 + (Wt / Zoom);
                        HOperatorSet.SetPart(hWindowControl2.HalconWindow, r1, c1, r2, c2);
                        HOperatorSet.ClearWindow(hWindowControl2.HalconWindow);
                        HOperatorSet.DispObj(templateregion, hWindowControl2.HalconWindow);
                    }
                }
            }
            catch (Exception)
            {

                throw;
            }

3.3 图像移动

基本原理:监控鼠标按下的事件,获取鼠标按下的x、y坐标位置;监控鼠标抬起的事件,获取鼠标最终抬起的x1、y1坐标,通过一定的比例换算得到需要显示的图像的左上角、右下角坐标位置,通过dev_setpart算子实现图像移动的效果。

  private void hWindowControl1_HMouseDown(object sender, HMouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left && roidrawingflag==0)
            {
                HTuple Row, Column, Button;
                HOperatorSet.GetMposition(hWindowControl1.HalconWindow, out Row, out Column, out Button);
                RowDown = Row;    //鼠标按下时的行坐标
                ColDown = Column; //鼠标按下时的列坐标
            }

       
        }
        private void hWindowControl1_HMouseUp(object sender, HMouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left && roidrawingflag == 0)
            {
                HTuple row1, col1, row2, col2, Row, Column, Button;
                HOperatorSet.GetMposition(hWindowControl1.HalconWindow, out Row, out Column, out Button);
                double RowMove = Row - RowDown;   //鼠标弹起时的行坐标减去按下时的行坐标,得到行坐标的移动值
                double ColMove = Column - ColDown;//鼠标弹起时的列坐标减去按下时的列坐标,得到列坐标的移动值
                HOperatorSet.GetPart(hWindowControl1.HalconWindow, out row1, out col1, out row2, out col2);//得到当前的窗口坐标
                HOperatorSet.SetPart(hWindowControl1.HalconWindow, row1 - RowMove, col1 - ColMove, row2 - RowMove, col2 - ColMove);//这里可能有些不好理解。以左上角原点为参考点
                HOperatorSet.SetSystem("flush_graphic", "false");
                HOperatorSet.ClearWindow(hWindowControl1.HalconWindow);
                HOperatorSet.SetSystem("flush_graphic", "true");
                HOperatorSet.DispObj(ho_Image, hWindowControl1.HalconWindow);
            }
                
        
        }

3.4 绘制图像roi区域

ROI区域绘制代码获取:在halcon软件中编写ROI绘制程序并导出成C#程序

private void btn_circle_draw_Click(object sender, EventArgs e)
        {
            roidrawingflag = 1;
            HObject ho_Circle;
            HTuple  hv_Row = null;
            HTuple hv_Column = null, hv_Radius = null;
            // Initialize local and output iconic variables 

            hWindowControl1.Focus();
            HOperatorSet.GenEmptyObj(out ho_Circle);
            HOperatorSet.GenEmptyObj(out templateregion);
            HOperatorSet.SetLineWidth(hWindowControl1.HalconWindow, 2);
            HOperatorSet.SetColor(hWindowControl1.HalconWindow, "red");

            HOperatorSet.DrawCircle(hWindowControl1.HalconWindow, out hv_Row, out hv_Column, out hv_Radius);
            ho_Circle.Dispose();
            HOperatorSet.GenCircle(out ho_Circle, hv_Row, hv_Column, hv_Radius);
            templateregion.Dispose();
            HOperatorSet.ReduceDomain(ho_Image, ho_Circle, out templateregion);
            HOperatorSet.GetImageSize(templateregion,out templatewidth,out templateheight);
            roidrawingflag = 0;
        }

注意:软件目前只做了圆形ROI绘制,其他的矩形、仿射矩形等ROI绘制方法一样。

3.5 开启多线程实现模板匹配(包含有参数设置、仿射变换、模板匹配)

form1占用了主线程,如果不开子线程用于模板匹配,主线程同时运行form1和模板匹配程序,会导致软件整体卡死;因此,需要使用Thread类开一个子线程用于模板匹配识别。

private void btn_serialreadimage_Click(object sender, EventArgs e)
        {
            //开启线程
            read_image = new Thread(read_image_serial);
            read_image.Start();
        }

        /// <summary>
        /// 模板匹配识别批量图片
        /// </summary>
        private void read_image_serial()
        {
            HTuple anglestart = null, angleend = null, numlevels = null, anglestep = null, optimization = null, metric = null, contrast = null, minconstrast = null, modelid = null;
            HObject outputcontours;
            HTuple hommate2d = null;
            if (templateregion != null)
            {
                HTuple templaterow, templatecolumn, templateangel, templatescore;
                //设置模板匹配算法参数
                if (ckb_numberpa.Checked)
                {
                    numlevels = "auto";
                }
                else
                {
                    numlevels = (int)numericUpDown1.Value;
                }
                HOperatorSet.TupleRad((int)numericUpDown2.Value, out anglestart);
                HOperatorSet.TupleRad((int)numericUpDown3.Value, out angleend);
                if (ckb_anglestep.Checked)
                {
                    anglestep = "auto";
                }
                else
                {
                    HOperatorSet.TupleRad((int)numericUpDown4.Value, out anglestep);
                }

                if (ckb_optimization.Checked)
                {
                    optimization = "auto";
                }
                else
                {
                    optimization = comboBox1.Text.ToString();
                }

                if (ckb_metric.Checked)
                {
                    metric = "use_polarity";
                }
                else
                {
                    metric = comboBox2.Text.ToString();
                }

                if (ckb_contrast.Checked)
                {
                    contrast = "auto";
                }
                else
                {
                    contrast = trackBar1.Value;
                }

                if (ckb_mincontrast.Checked)
                {
                    minconstrast = "auto";
                }
                else
                {
                    minconstrast = trackBar2.Value;
                }

                HOperatorSet.CreateShapeModel(templateregion, numlevels, anglestart, angleend, anglestep, optimization, metric, contrast, minconstrast, out modelid);
                HOperatorSet.GenEmptyObj(out outputcontours);
                outputcontours.Dispose();
                HOperatorSet.HomMat2dIdentity(out hommate2d);

                HObject ho_Image = null, outputregion;
                // Local control variables 
                HTuple hv_ImageFiles = null, hv_Index = null, displayfont;
                HTuple homat2dtras, homat2drotate;
                double rateimage, ratewin;
                double row1, column1, row2, column2;
                HTuple imagewidth, imageheigth, partwidth, partheigth;
                // Initialize local and output iconic variables 
                HOperatorSet.GenEmptyObj(out ho_Image);
                //Image Acquisition 01: Code generated by Image Acquisition 01
                HOperatorSet.ListFiles("C:/Users/Public/Documents/MVTec/HALCON-17.12-Progress/examples/images/board", "files", out hv_ImageFiles);
                HOperatorSet.TupleRegexpSelect(hv_ImageFiles, ".*png", out hv_ImageFiles);
                

                for (hv_Index = 0; (int)hv_Index <= (int)((new HTuple(hv_ImageFiles.TupleLength()
                )) - 1); hv_Index = (int)hv_Index + 1)
                {
                    HOperatorSet.GenEmptyObj(out ho_Image);
                    ho_Image.Dispose();
                    HOperatorSet.ReadImage(out ho_Image, hv_ImageFiles.TupleSelect(hv_Index));
                    HOperatorSet.GetImageSize(ho_Image, out imagewidth, out imageheigth);
                    partwidth = hWindowControl1.Width;
                    partheigth = hWindowControl1.Height;
                    //计算图像比率和窗体比例
                    rateimage = 1.0 * imagewidth / imageheigth;
                    ratewin = 1.0 * partwidth / partheigth;
                    //自适应显示图像
                    HOperatorSet.ClearWindow(hWindowControl1.HalconWindow);

                    if (rateimage <= ratewin )
                    {
                        row1 = 0;
                        column1 = -(1.0 * imageheigth / partheigth * partwidth - imagewidth) * 1.0 / 2;
                        row2 = row1 + imageheigth;
                        column2 = column1 + 1.0 * partwidth * imageheigth / partheigth;
                        HOperatorSet.SetPart(hWindowControl1.HalconWindow, row1, column1, row2, column2);
                        HOperatorSet.FindShapeModel(ho_Image, modelid, anglestart, angleend, 0.5, 1, 0, "least_squares", 1, 0.7, out templaterow, out templatecolumn, out templateangel, out templatescore);
                        HOperatorSet.GetShapeModelContours(out outputcontours, modelid, 1);
                        try
                        {
                                HOperatorSet.HomMat2dTranslate(hommate2d, templaterow, templatecolumn, out homat2dtras);
                                HOperatorSet.HomMat2dRotate(homat2dtras, templateangel, templaterow, templatecolumn, out homat2drotate);
                                HOperatorSet.AffineTransContourXld(outputcontours, out outputregion, homat2drotate);

                                HOperatorSet.SetColor(hWindowControl1.HalconWindow, "blue");
                                HOperatorSet.SetLineWidth(hWindowControl1.HalconWindow, 1.5);

                                HOperatorSet.DispObj(ho_Image, hWindowControl1.HalconWindow);
                                HOperatorSet.DispObj(outputregion, hWindowControl1.HalconWindow);
                                if (outputcontours != null)
                                {
                                    HOperatorSet.SetTposition(hWindowControl1.HalconWindow, 20, 20);
                                    HOperatorSet.SetColor(hWindowControl1.HalconWindow, "red");
                                    HOperatorSet.QueryFont(hWindowControl1.HalconWindow,out displayfont);

                                    HOperatorSet.SetFont(hWindowControl1.HalconWindow, displayfont[0]+ "-Bold-25");
                                    HOperatorSet.WriteString(hWindowControl1.HalconWindow, "The result is OK");
                                }

                        }
                        catch (Exception)
                        {
                            throw;
                        }
                    }
                    HOperatorSet.WaitSeconds(1);
                    if (hv_Index == (hv_ImageFiles.TupleLength() - 1))
                    {
                        HOperatorSet.ClearWindow(hWindowControl1.HalconWindow);
                        read_image.Abort();
                    }
                }

            }
            else
            {
                MessageBox.Show("请添加模板图像");
                read_image.Abort();
            }
                
            
        }

3.2.1 模板匹配参数设置

  if (ckb_numberpa.Checked)
                {
                    numlevels = "auto";
                }
                else
                {
                    numlevels = (int)numericUpDown1.Value;
                }
                HOperatorSet.TupleRad((int)numericUpDown2.Value, out anglestart);
                HOperatorSet.TupleRad((int)numericUpDown3.Value, out angleend);
                if (ckb_anglestep.Checked)
                {
                    anglestep = "auto";
                }
                else
                {
                    HOperatorSet.TupleRad((int)numericUpDown4.Value, out anglestep);
                }

                if (ckb_optimization.Checked)
                {
                    optimization = "auto";
                }
                else
                {
                    optimization = comboBox1.Text.ToString();
                }

                if (ckb_metric.Checked)
                {
                    metric = "use_polarity";
                }
                else
                {
                    metric = comboBox2.Text.ToString();
                }

                if (ckb_contrast.Checked)
                {
                    contrast = "auto";
                }
                else
                {
                    contrast = trackBar1.Value;
                }

                if (ckb_mincontrast.Checked)
                {
                    minconstrast = "auto";
                }
                else
                {
                    minconstrast = trackBar2.Value;
                }

                HOperatorSet.CreateShapeModel(templateregion, numlevels, anglestart, angleend, anglestep, optimization, metric, contrast, minconstrast, out modelid);
                HOperatorSet.GenEmptyObj(out outputcontours);
                outputcontours.Dispose();

3.2.2 仿射变换

HOperatorSet.HomMat2dTranslate(hommate2d, templaterow, templatecolumn, out homat2dtras);
                                HOperatorSet.HomMat2dRotate(homat2dtras, templateangel, templaterow, templatecolumn, out homat2drotate);
                                HOperatorSet.AffineTransContourXld(outputcontours, out outputregion, homat2drotate);

注意:模板匹配算法找到的轮廓起始坐标为窗口左上角坐标,角度为0度

3.2.3 模板匹配

HOperatorSet.CreateShapeModel(templateregion, numlevels, anglestart, angleend, anglestep, optimization, metric, contrast, minconstrast, out modelid);
HOperatorSet.FindShapeModel(ho_Image, modelid, anglestart, angleend, 0.5, 1, 0, "least_squares", 1, 0.7, out templaterow, out templatecolumn, out templateangel, out templatescore);
                        HOperatorSet.GetShapeModelContours(out outputcontours, modelid, 1);

4. 后期待完善

4.1 日志开发

4.2 其他ROI功能

4.3 不同控件之间的互锁

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值