矩阵求解拟合圆(最小二乘法) C#实现

圆的标准方程为:

(X - A)^{^{2}} + (Y-B)^{2} = r^{2} =>X ^{^{2}} + Y^{2} + aX + bY + c = 0      

其中

A=-\frac{a}{2}B=-\frac{b}{2}r=\frac{1}{2}(a^{2}+b^{2}-4c)^{\frac{1}{2}}

由圆的标准方程可以得出矩阵表示

\begin{bmatrix} &-X_{1} &-Y_{1} &-1 \\ &-X_{2} &-Y_{2} &-1 \\ &--- &--- &---\\ &-X_{n} &-Y_{n} &-1 \end{bmatrix}\cdot \begin{bmatrix} a\\ b\\ c \end{bmatrix} = \begin{bmatrix} X_{1}^{2} + Y_{1}^{2}\\ X_{2}^{2} + Y_{2}^{2}\\ ---\\ X_{n}^{2} + Y_{n}^{2} \end{bmatrix}

由此已经得出R\cdot A = Y的矩阵形式。其最小二乘解为

A=(R^{T}\cdot R)^{-1}\cdot R^{T}\cdot Y

由以上公式便可写出最小二乘法拟合圆的公式,代码由C# Math.Net包实现

  private static int FitCircle(List pointFs,out float CenterX, out float CenterY,out float CenterR)
        {
            Matrix YMat;
            Matrix RMat;
            Matrix AMat;
            List YLit = new List();
            List RLit = new List();
            //------构建Y矩阵
            foreach (var pointF in pointFs)
                YLit.Add(pointF.X * pointF.X + pointF.Y * pointF.Y);
            float[,] Yarray = new float[YLit.Count, 1];
            for (int i = 0; i < YLit.Count; i++)
                Yarray[i, 0] = YLit[i]; 
            YMat = CreateMatrix.DenseOfArray(Yarray);

            //构建R矩阵
            foreach (var pointF in pointFs)
                RLit.Add(new float[] { -pointF.X, -pointF.Y, -1});
            float[,] Rarray = new float[RLit.Count, 3];
            for (int i = 0; i < RLit.Count; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    Rarray[i, j] = RLit[i][j];
                }
            }
            RMat = CreateMatrix.DenseOfArray(Rarray);
            Matrix RTMat = RMat.Transpose();
            Matrix RRTInvMat = (RTMat.Multiply(RMat)).Inverse();
            AMat = RRTInvMat.Multiply(RTMat.Multiply(YMat));

            float[,] Aarray = AMat.ToArray();
            float A = Aarray[0, 0];
            float B = Aarray[1, 0];
            float C = Aarray[2, 0];
            CenterX = A / -2.0f;
            CenterY = B / -2.0f;
            CenterR = (float)(Math.Sqrt((A * A + B * B - 4 * C)) / 2.0f);
            return 0x0000;
        }

再建立一个Winform验证下

 private void btnFit_Click(object sender, EventArgs e)
        {

            float CenterX;
            float CenterY;
            float CenterR;
       
            FitCircle(CircleFitLit, out CenterX, out CenterY, out CenterR);

            g.DrawEllipse(new Pen(Color.Blue,1),CenterX - CenterR, CenterY - CenterR, CenterR * 2, CenterR * 2);




        }

        private void Form1_MouseClick(object sender, MouseEventArgs e)
        {
            g = this.CreateGraphics();

            g.FillEllipse(Brushes.Red, e.Location.X - 5, e.Location.Y - 5, 10, 10);
            CircleFitLit.Add(new PointF(e.Location.X, e.Location.Y));
        }

最后的效果如下

矩阵求解拟合圆(最小二乘法) C#实现_第1张图片

 

你可能感兴趣的:(C#,机器视觉)