机器视觉入门之路(五六,找圆工具的设计B,c#)

本文详细介绍了在图像处理中如何使用特定工具和技术来检测并拟合圆形区域。通过在感兴趣区域运行找圆工具,文章展示了如何在图像中识别圆形特征,并利用样本穿越点进行圆的拟合。此外,还提供了具体的代码实现细节,包括变量声明、鼠标事件响应、画图函数调用以及拟合圆的数学公式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在我们截取的感兴趣区域里,我们让找圆工具运行起来:

1,   mg_CircleCaliper gaugeCir;//增加变量声明

2,    gaugeCir = new mg_CircleCaliper();//form()中初始化
       gaugeCir.m_cirRoi.m_RoiCircle.Init(100, 100, 50);

3,在图像控件mousemove事件响应中添加

  PointF point = new PointF(e.X, e.Y);          
   bool status = false;
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                status = true;
            }

     gaugeCir.m_cirRoi.DrawRectFrame(status, point);
      this.Cursor = gaugeCir.m_cirRoi.m_cur;

     pictureBoxRoiImg.Invalidate(false);

4,在图像控件Paint事件响应中添加

 gaugeCir.m_cirRoi.m_RoiCircle.Draw(g, p, gb_dirCirle);

   if (m_bclonebuf8 == true)//克隆图像不为空
                for (int i = 0; i < gaugeCir.SPLITNUM; i++)
                {
                    PointF[] BackResult = new PointF[9];
                    PointF[] fnback0 = new PointF[gaugeCir.SPLITNUM];
                    PointF[] inback = new PointF[gaugeCir.SPLITNUM];
                    if (i % 2 == 0)//0246区域找穿越点
                    {
                        fnback0 = gaugeCir.SPlitPassThroughPointsimprove(ref clonetempbuffer8,
                            ref BackResult, Convert.ToInt32(tbThresforCirle.Text), gb_dirCirle, new Size(_RoiW, _RoiH),                           
                           ref gaugeCir.m_cirRoi.m_RoiCircle.onRadpointOut[i],
                           ref gaugeCir.m_cirRoi.m_RoiCircle.onRadpointIn[i], ref inback);
                    //显示出线图像0246区域
                            for (int iii = 0; iii < 8; iii++)
                            {
                                g.DrawLine(new Pen(Color.Pink), inback[iii], fnback0[iii]);
                            }
                    }
                    else//1357区域找穿越点
                    {
                        fnback0 = gaugeCir.SPlitPassThroughPointsimprove1357(ref clonetempbuffer8,
                            ref BackResult, Convert.ToInt32(tbThresforCirle.Text), gb_dirCirle, new Size(_RoiW, _RoiH),                            
                          ref gaugeCir.m_cirRoi.m_RoiCircle.onRadpointOut[i],
                          ref gaugeCir.m_cirRoi.m_RoiCircle.onRadpointIn[i], ref inback);
                        //显示出线图像1357区域
                            for (int iii = 0; iii < 8; iii++)
                            {
                                g.DrawLine(new Pen(Color.Pink), inback[iii], fnback0[iii]);
                            }
                    }

   for (int ii = 0; ii < 9; ii++)
                    {
                        g.DrawLine(new Pen(Color.Red), BackResult[ii].X, BackResult[ii].Y - 3, BackResult[ii].X, BackResult[ii].Y + 3);
                        g.DrawLine(new Pen(Color.Red), BackResult[ii].X - 3, BackResult[ii].Y, BackResult[ii].X + 3, BackResult[ii].Y);                       }

搞定!拖动试试看,有没有发现,他很像我们的眼睛?!调整,在有圆形的地方,样本穿越点(红色的叉叉示意)出来了没?是的,有圆,我们应该把它拟合出来。以下是拟合圆函数:siglecontour样本点,num样本点数,(aa,bb),r是返回圆心,半径

  private void fitCircle(List<PointF> siglecontour, int num, ref double aa, ref double bb, ref double r)
        {//值大过了银河系,怎么办?
            double X1, X2, X3, Y1, Y2, Y3, X1Y1, X1Y2, X2Y1;
            double C, D, E, G, H, N;
            double a, b, c;
            if (num < 3)
            { return; }
            X1 = X2 = X3 = Y1 = Y2 = Y3 = X1Y1 = X1Y2 = X2Y1 = 0;
            for (int i = 0; i < num; i++)
            {
                X1 += (siglecontour[i].X - siglecontour[0].X);
                X2 += (siglecontour[i].X - siglecontour[0].X) * (siglecontour[i].X - siglecontour[0].X);
                X3 += (siglecontour[i].X - siglecontour[0].X) * (siglecontour[i].X - siglecontour[0].X) * (siglecontour[i].X - siglecontour[0].X);
                Y1 += (siglecontour[i].Y - siglecontour[0].Y);
                Y2 += (siglecontour[i].Y - siglecontour[0].Y) * (siglecontour[i].Y - siglecontour[0].Y);
                Y3 += (siglecontour[i].Y - siglecontour[0].Y) * (siglecontour[i].Y - siglecontour[0].Y) * (siglecontour[i].Y - siglecontour[0].Y);
                X1Y1 += (siglecontour[i].Y - siglecontour[0].Y) * (siglecontour[i].X - siglecontour[0].X);
                X1Y2 += (siglecontour[i].Y - siglecontour[0].Y) * (siglecontour[i].Y - siglecontour[0].Y) * (siglecontour[i].X - siglecontour[0].X);
                X2Y1 += (siglecontour[i].X - siglecontour[0].X) * (siglecontour[i].X - siglecontour[0].X) * (siglecontour[i].Y - siglecontour[0].Y);

            }
            N = num;
            C = N * X2 - X1 * X1;
            D = N * X1Y1 - X1 * Y1;
            E = N * X3 + N * X1Y2 - (X2 + Y2) * X1;
            G = N * Y2 - Y1 * Y1;
            H = N * X2Y1 + N * Y3 - (X2 + Y2) * Y1;
            a = (H * D - E * G) / (1.0 * (C * G - D * D));
            b = (H * C - E * D) / (1.0 * (D * D - G * C));
            c = -(a * X1 + b * Y1 + X2 + Y2) / (N * 1.0);
            aa = -a / 2.0 + siglecontour[0].X;
            bb = -b / 2.0 + siglecontour[0].Y;
            r = Math.Sqrt(a * a + b * b - 4 * c) / 2.0;
        }

找圆工具完成,早期的iphone手机上有个menubutton(home键),他就是圆形的,我们就是通过这种技术给他贴上去的(开玩笑呐!别当真)。

(待续...............)最后看一下效果图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值