c++最小二乘法拟合图像中多个圆的圆心,并显示圆心半径大小
时间: 2023-07-02 22:15:27 浏览: 167
首先,我们可以通过霍夫变换检测出图像中的多个圆,并获取它们的半径和中心坐标。然后,我们可以使用最小二乘法对这些圆心坐标进行拟合,以获得一个更精确的圆心位置。
以下是一个使用 OpenCV 实现此功能的示例代码:
```c++
#include <opencv2/opencv.hpp>
#include <iostream>
#include <cmath>
using namespace cv;
using namespace std;
int main()
{
Mat src = imread("image.jpg", IMREAD_GRAYSCALE);
if (src.empty()) {
cout << "Could not read the image!" << endl;
return -1;
}
// 霍夫变换检测圆
vector<Vec3f> circles;
HoughCircles(src, circles, HOUGH_GRADIENT, 1, src.rows / 8, 200, 50, 0, 0);
// 显示检测到的圆
Mat dst;
cvtColor(src, dst, COLOR_GRAY2BGR);
for (size_t i = 0; i < circles.size(); i++)
{
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
circle(dst, center, radius, Scalar(0, 0, 255), 2);
}
imshow("circles", dst);
// 最小二乘法拟合圆心
int n = circles.size();
Mat A(n, 3, CV_64F), B(n, 1, CV_64F);
for (int i = 0; i < n; i++) {
A.at<double>(i, 0) = 2 * circles[i][0];
A.at<double>(i, 1) = 2 * circles[i][1];
A.at<double>(i, 2) = -1;
B.at<double>(i, 0) = circles[i][0] * circles[i][0] + circles[i][1] * circles[i][1];
}
Mat X = (A.t() * A).inv() * A.t() * B;
double x0 = X.at<double>(0, 0);
double y0 = X.at<double>(1, 0);
double r = sqrt(x0 * x0 + y0 * y0 - X.at<double>(2, 0));
// 显示拟合结果
for (size_t i = 0; i < circles.size(); i++)
{
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
circle(dst, center, 3, Scalar(0, 255, 0), -1);
}
circle(dst, Point(cvRound(x0), cvRound(y0)), cvRound(r), Scalar(0, 255, 0), 2);
imshow("result", dst);
waitKey();
return 0;
}
```
在此示例中,我们首先使用霍夫变换检测图像中的圆,并绘制出检测到的圆。然后,我们使用最小二乘法对圆心坐标进行拟合,并计算出拟合出的圆的半径和圆心坐标。最后,我们在原始图像上绘制出拟合结果,其中圆心用绿色点标记,拟合出的圆用绿色圆标记。
阅读全文