最小二乘拟合圆曲线方程为:R²=(X-A)²+(Y-B)²
因此只需求出圆心坐标(A,B)和半径R即可。
拟合圆的详细推导公式见:http://blog.163.com/small_duan/blog/static/28584262200872340079/
这里只给出使用C#编写的拟合圆程序:
/// <summary>
/// 拟合圆
/// </summary>
private struct Circle
{
public double X;//圆心X
public double Y;//圆心Y
public double R;//半径R
}
/// <summary>
/// 定义的拟合点
/// </summary>
private struct PixelPoint
{
public double x;
public double y;
}
/// <summary>
/// 拟合圆程序
/// </summary>
/// <param name="pPointList">要拟合点集</param>
/// <returns>返回圆对象</returns>
private Circle FittingCircle(List<PixelPoint> pPointList)
{
Circle pCircle=new Circle();
if (pPointList.Count < 3)
{
XtraMessageBox.Show("最少需要三个点进行拟合");
return pCircle;
}
double X1 = 0;
double Y1 = 0;
double X2 = 0;
double Y2 = 0;
double X3 = 0;
double Y3 = 0;
double X1Y1 = 0;
double X1Y2 = 0;
double X2Y1 = 0;
for (int i = 0; i < pPointList.Count; i++)
{
X1 = X1 + pPointList[i].x;
Y1 = Y1 + pPointList[i].y;
X2 = X2 + pPointList[i].x * pPointList[i].x;
Y2 = Y2 + pPointList[i].y * pPointList[i].y;
X3 = X3 + pPointList[i].x * pPointList[i].x * pPointList[i].x;
Y3 = Y3 + pPointList[i].y * pPointList[i].y * pPointList[i].y;
X1Y1 = X1Y1 + pPointList[i].x * pPointList[i].y;
X1Y2 = X1Y2 + pPointList[i].x * pPointList[i].y * pPointList[i].y;
X2Y1 = X2Y1 + pPointList[i].x * pPointList[i].x * pPointList[i].y;
}
double C, D, E, G, H, N;
double a, b, c;
N = pPointList.Count;
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) / (C * G - D * D);
b = (H * C - E * D) / (D * D - G * C);
c = -(a * X1 + b * Y1 + X2 + Y2) / N;
pCircle.X = a / (-2);
pCircle.Y = b / (-2);
pCircle.R = Math.Sqrt(a * a + b * b - 4 * c) / 2;
return pCircle;
}
拟合结果如下: