机器视觉图像处理中常用到圆形检测,准确地拟合圆轮廓是测量圆直径尺寸的前提和保证。霍夫圆检测容易受到变形圆或缺损圆的影响,改进的最小二乘法可以提高拟合和尺寸测量精度。
1、公式推导
最小二乘法通过最小化误差的平方和找到一组数据的最佳函数匹配。 最小二乘法是用最简的方法求得一些绝对不可知的真值,而令误差平方之和为最小。
2、代码
double sumX = 0.0;
double sumY = 0.0;
double sumX2 = 0.0;
double sumY2 = 0.0;
double sumX3 = 0.0;
double sumY3 = 0.0;
double sumXY = 0.0;
double sumX1Y2 = 0.0;
double sumX2Y1 = 0.0;
const double N = (double)points.size();
for (int i = 0; i < points.size(); ++i)
{
double x = points.at(i).x;
double y = points.at(i).y;
double x2 = x * x;
double y2 = y * y;
double x3 = x2 *x;
double y3 = y2 *y;
double xy = x * y;
double x1y2 = x * y2;
double x2y1 = x2 * y;
sumX += x;
sumY += y;
sumX2 += x2;
sumY2 += y2;
sumX3 += x3;
sumY3 += y3;
sumXY += xy;
sumX1Y2 += x1y2;
sumX2Y1 += x2y1;
}
double C = N * sumX2 - sumX * sumX;
double D = N * sumXY - sumX * sumY;
double E = N * sumX3 + N * sumX1Y2 - (sumX2 + sumY2) * sumX;
double G = N * sumY2 - sumY * sumY;
double H = N * sumX2Y1 + N * sumY3 - (sumX2 + sumY2) * sumY;
double denominator = C * G - D * D;
if (std::abs(denominator) < DBL_EPSILON) return false;
double a = (H * D - E * G) / (denominator);
denominator = D * D - G * C;
if (std::abs(denominator) < DBL_EPSILON) return false;
double b = (H * C - E * D) / (denominator);
double c = -(a * sumX + b * sumY + sumX2 + sumY2) / N;
Point3f tempcircle;
tempcircle.x = a / (-2);
tempcircle.y = b / (-2);
tempcircle.z = std::sqrt(a * a + b * b - 4 * c) / 2;
Point center(tempcircle.x, tempcircle.y);
cout << "tempcircle.x = " << tempcircle.x << "tempcircle.y = " << tempcircle.y << "tempcircle.z = " << tempcircle.z << endl;
3、结果展示
原方法拟合失败的主要原因是受缺陷点的影响,通过圆心修正法,将圆心不断修正,直至接近准确圆心。红色拟合线是原方法拟合结果,绿色拟合线是最终拟合结果,通过图像比较,圆拟合效果有较大的改进。