经典算法——绘制空心圆续(二)

实际应用中,往往需要三点确定一个圆。

例如,在机器人视觉标定中,为了能不用手工创建工具坐标,就可以通过三点定圆的方式算出工具坐标的中心在哪里。


我们知道,如果三点不共线的情况下是可以产生一个圆的,有关的公式推导见下面的贴子。

三点确定一个圆的算法(C#代码)


这里勇哥提供公式的实现代码:


private Tuple<PointF, double> drawCircle3P(PointF pt1, PointF pt2, PointF pt3)
        {
            double x1 = pt1.X, x2 = pt2.X, x3 = pt3.X;
            double y1 = pt1.Y, y2 = pt2.Y, y3 = pt3.Y;
            double a = x1 - x2;
            double b = y1 - y2;
            double c = x1 - x3;
            double d = y1 - y3;
            double e = ((x1 * x1 - x2 * x2) + (y1 * y1 - y2 * y2)) / 2.0;
            double f = ((x1 * x1 - x3 * x3) + (y1 * y1 - y3 * y3)) / 2.0;
            double det = b * c - a * d;
           
            if(Math.Abs(det)<1e-5)
            {
                return new Tuple<PointF, double>(new PointF(0, 0), -1);
            }

            double x0 = -(d * e - b * f) / det;
            double y0 = -(a * f - c * e) / det;
            var radius = Math.Sqrt((x1 - x0)*(x1 - x0)+(y1 - y0)* (y1 - y0));
            return new Tuple<PointF, double>(new PointF((float)x0,(float)y0), radius);
        }

        private static PointF FitCenter(List<PointF> pts, double epsilon = 0.1)
        {
            try
            {
                double totalX = 0, totalY = 0;
                int setCount = 0;

                for (int i = 0; i < pts.Count; i++)
                {
                    for (int j = 1; j < pts.Count; j++)
                    {
                        for (int k = 2; k < pts.Count; k++)
                        {
                            double delta = (pts[k].X - pts[j].X) * (pts[j].Y - pts[i].Y) - (pts[j].X - pts[i].X) * (pts[k].Y - pts[j].Y);

                            if (Math.Abs(delta) > epsilon)
                            {
                                double ii = Math.Pow(pts[i].X, 2) + Math.Pow(pts[i].Y, 2);
                                double jj = Math.Pow(pts[j].X, 2) + Math.Pow(pts[j].Y, 2);
                                double kk = Math.Pow(pts[k].X, 2) + Math.Pow(pts[k].Y, 2);

                                double cx = ((pts[k].Y - pts[j].Y) * ii + (pts[i].Y - pts[k].Y) * jj + (pts[j].Y - pts[i].Y) * kk) / (2 * delta);
                                double cy = -((pts[k].X - pts[j].X) * ii + (pts[i].X - pts[k].X) * jj + (pts[j].X - pts[i].X) * kk) / (2 * delta);

                                totalX += cx;
                                totalY += cy;

                                setCount++;
                            }
                        }
                    }
                }

                if (setCount == 0)
                {
                    return PointF.Empty;
                }

                return new PointF((float)totalX / setCount, (float)totalY / setCount);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
                return PointF.Empty;
            }
        }
        
        private void button6_Click(object sender, EventArgs e)
        {
            //px:=[191,198,190]
            //py:=[191, 228, 260]
            var ary1=drawCircle3P(new Point(191, 191), new Point(198,228), new Point(190,260));
            var ary2 = FitCenter(new List<PointF>() { new PointF(191, 191), new PointF(198, 228), new PointF(190, 260) });
        }


这里勇哥提了两个实现,函数FitCenter只不过比drawCircle3P计算精度要高一点。因为PointF只能保存float型,因此小数字点后只有4位。

两个函数的运行结果如下:


x= 115.6615, Y=224.4154

X = 115.661537 Y = 224.41539


勇哥随便用halcon验证了一下,证明结果正确。

image.png


--------------------- 

作者:hackpig
来源:
www.skcircle.com
版权声明:本文为博主原创文章,转载请附上博文链接!


本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2025年4月    »
123456
78910111213
14151617181920
21222324252627
282930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864