C++ 中圆的最小二乘法
Least Square for Circle in c++
我应该找到这个 çember 方程,我为此写了四个代码,但他们有一半代码没有完成(我无法完成它:()
首先我写了一个代码来找到这些黑点坐标:
Mat img=imread("n.jpg");
Mat thresh;
threshold(img,thresh,150,500,THRESH_BINARY_INV);
// int point[thresh.rows][thresh.cols];
vector<int> x,y;
for(int i = 0; i < thresh.rows; ++i) {
for(int j = 0; j < thresh.cols; ++j) {
int b = int(thresh.at<cv::Vec3b>(i,j)[0]);//burada biz b g r yi kısaca yazabilmek için tanımladık
int g = int(thresh.at<cv::Vec3b>(i,j)[1]);
int r = int(thresh.at<cv::Vec3b>(i,j)[2]);
//cout<<b<<" "<<g<<" "<<r<<endl;
// cout<<i<<" "<<j<<endl;
if(b==255&&g==255&&r==255)
{
x.push_back(i);
y.push_back(j);
cout<<i<<" "<<j<<endl;
}
//cout<<b<<" "<<g<<" "<<r<<endl;
}
}
而且比
1)我写了一个行列式代码来找到给定 3 点的圆
float determinant(float arr[][3])
{
float det=0.0;
int i;
for(i=0;i<3;i++)
det = det + (arr[0][i]*(arr[1][(i+1)%3]*arr[2][(i+2)%3] - arr[1][(i+2)%3]*arr[2][(i+1)%3]));
return det;
}
int main()
{
float matris1[3][3],matris2[3][3],matris3[3][3];
float x[3],y[3];//x1,x2,x3/y1,y2,y3
int i,j;
printf("x1 x2 ve x3 u giriniz\n");
scanf("%f%f%f",&x[0],&x[1],&x[2]);
printf("y1 y2 ve y3 u giriniz\n");
scanf("%f%f%f",&y[0],&y[1],&y[2]);
//matris1 i oluşturma
for(i=0;i<3;i++)
for(j=0;j<3;j++)
if(j==0)
matris1[i][j]=pow(x[i],2)+pow(y[i],2);
else if(j==1)
matris1[i][j]=y[i];
else
matris1[i][j]=1;
//matris2 yi oluşturma
for(i=0;i<3;i++)
for(j=0;j<3;j++)
if(j==0)
matris2[i][j]=x[i];
else if(j==1)
matris2[i][j]=y[i];
else
matris2[i][j]=1;
//matris3 yi oluşturma
for(i=0;i<3;i++)
for(j=0;j<3;j++)
if(j==0)
matris3[i][j]=x[i];
else if(j==1)
matris3[i][j]=pow(x[i],2)+pow(y[i],2);
else
matris3[i][j]=1;
//matris1 i ve determinantını yazdırma
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
printf("%.2f ",matris1[i][j]);
}
printf("\n");
}
printf("Determinanti1 =%.2f \n\n",determinant(matris1));
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
printf("%.2f ",matris2[i][j]);
}
printf("\n");
}
printf("Determinanti2 =%.2f \n\n",determinant(matris2));
//matris3 i ve determinantını yazdırma
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
printf("%.2f ",matris3[i][j]);
}
printf("\n");
}
printf("Determinanti3 =%.2f \n\n",determinant(matris3));
float a,b;
a=determinant(matris1)/(2*determinant(matris2));
b=determinant(matris3)/(2*determinant(matris2));
printf("%.2f ",a);
printf("%.2f ",b);
float yaricap;
yaricap=sqrt((x[0]-a)*(x[0]-a)+(y[0]-b)*(y[0]-b));
printf("yaricap =%.2f \n\n",yaricap);
}
但是这段代码有 3 点,但我有很多点,我无法实现
2)最小二乘的代码:
typedef struct {
double x, y;
} Point2;
int CircleFit(int N, Point2 * P, double *pa, double *pb, double *pr)
{
const int maxIterations = 256;
const double tolerance = 1e-06;
double a, b, r;
int i, j;
double xAvr = 0.0;
double yAvr = 0.0;
for (i = 0; i < N; i++) {
xAvr += P[i].x;
yAvr += P[i].y;
}
xAvr /= N;
yAvr /= N;
a = xAvr;
b = yAvr;
for (j = 0; j < maxIterations; j++) {
double a0 = a;
double b0 = b;
double LAvr = 0.0;
double LaAvr = 0.0;
double LbAvr = 0.0;
for (i = 0; i < N; i++) {
double dx = P[i].x - a;
double dy = P[i].y - b;
double L = sqrt(dx * dx + dy * dy);
if (fabs(L) > tolerance) {
LAvr += L;
LaAvr -= dx / L;
LbAvr -= dy / L;
}
}
LAvr /= N;
LaAvr /= N;
LbAvr /= N;
a = xAvr + LAvr * LaAvr;
b = yAvr + LAvr * LbAvr;
r = LAvr;
if (fabs(a - a0) <= tolerance && fabs(b - b0) <= tolerance)
break;
}
*pa = a;
*pb = b;
*pr = r;
return (j < maxIterations ? j : -1);
}
enum {
M_SHOW_CIRCLE, M_CIRCLE_INFO, M_RESET_POINTS, M_QUIT
};
但我不知道如何将我的观点和这个结合起来??
感谢您的进阶
如果一组点是对称的,最好的方法是对 x 和 y 求和,然后您将找到中心,然后计算中心和一组点之间的平均距离,使其具有半径
这是一个圆回归问题我确定你可以问https://math.stackexchange.com/
连本站都有例子
我应该找到这个 çember 方程,我为此写了四个代码,但他们有一半代码没有完成(我无法完成它:() 首先我写了一个代码来找到这些黑点坐标:
Mat img=imread("n.jpg");
Mat thresh;
threshold(img,thresh,150,500,THRESH_BINARY_INV);
// int point[thresh.rows][thresh.cols];
vector<int> x,y;
for(int i = 0; i < thresh.rows; ++i) {
for(int j = 0; j < thresh.cols; ++j) {
int b = int(thresh.at<cv::Vec3b>(i,j)[0]);//burada biz b g r yi kısaca yazabilmek için tanımladık
int g = int(thresh.at<cv::Vec3b>(i,j)[1]);
int r = int(thresh.at<cv::Vec3b>(i,j)[2]);
//cout<<b<<" "<<g<<" "<<r<<endl;
// cout<<i<<" "<<j<<endl;
if(b==255&&g==255&&r==255)
{
x.push_back(i);
y.push_back(j);
cout<<i<<" "<<j<<endl;
}
//cout<<b<<" "<<g<<" "<<r<<endl;
}
}
而且比 1)我写了一个行列式代码来找到给定 3 点的圆
float determinant(float arr[][3])
{
float det=0.0;
int i;
for(i=0;i<3;i++)
det = det + (arr[0][i]*(arr[1][(i+1)%3]*arr[2][(i+2)%3] - arr[1][(i+2)%3]*arr[2][(i+1)%3]));
return det;
}
int main()
{
float matris1[3][3],matris2[3][3],matris3[3][3];
float x[3],y[3];//x1,x2,x3/y1,y2,y3
int i,j;
printf("x1 x2 ve x3 u giriniz\n");
scanf("%f%f%f",&x[0],&x[1],&x[2]);
printf("y1 y2 ve y3 u giriniz\n");
scanf("%f%f%f",&y[0],&y[1],&y[2]);
//matris1 i oluşturma
for(i=0;i<3;i++)
for(j=0;j<3;j++)
if(j==0)
matris1[i][j]=pow(x[i],2)+pow(y[i],2);
else if(j==1)
matris1[i][j]=y[i];
else
matris1[i][j]=1;
//matris2 yi oluşturma
for(i=0;i<3;i++)
for(j=0;j<3;j++)
if(j==0)
matris2[i][j]=x[i];
else if(j==1)
matris2[i][j]=y[i];
else
matris2[i][j]=1;
//matris3 yi oluşturma
for(i=0;i<3;i++)
for(j=0;j<3;j++)
if(j==0)
matris3[i][j]=x[i];
else if(j==1)
matris3[i][j]=pow(x[i],2)+pow(y[i],2);
else
matris3[i][j]=1;
//matris1 i ve determinantını yazdırma
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
printf("%.2f ",matris1[i][j]);
}
printf("\n");
}
printf("Determinanti1 =%.2f \n\n",determinant(matris1));
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
printf("%.2f ",matris2[i][j]);
}
printf("\n");
}
printf("Determinanti2 =%.2f \n\n",determinant(matris2));
//matris3 i ve determinantını yazdırma
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
printf("%.2f ",matris3[i][j]);
}
printf("\n");
}
printf("Determinanti3 =%.2f \n\n",determinant(matris3));
float a,b;
a=determinant(matris1)/(2*determinant(matris2));
b=determinant(matris3)/(2*determinant(matris2));
printf("%.2f ",a);
printf("%.2f ",b);
float yaricap;
yaricap=sqrt((x[0]-a)*(x[0]-a)+(y[0]-b)*(y[0]-b));
printf("yaricap =%.2f \n\n",yaricap);
}
但是这段代码有 3 点,但我有很多点,我无法实现 2)最小二乘的代码:
typedef struct {
double x, y;
} Point2;
int CircleFit(int N, Point2 * P, double *pa, double *pb, double *pr)
{
const int maxIterations = 256;
const double tolerance = 1e-06;
double a, b, r;
int i, j;
double xAvr = 0.0;
double yAvr = 0.0;
for (i = 0; i < N; i++) {
xAvr += P[i].x;
yAvr += P[i].y;
}
xAvr /= N;
yAvr /= N;
a = xAvr;
b = yAvr;
for (j = 0; j < maxIterations; j++) {
double a0 = a;
double b0 = b;
double LAvr = 0.0;
double LaAvr = 0.0;
double LbAvr = 0.0;
for (i = 0; i < N; i++) {
double dx = P[i].x - a;
double dy = P[i].y - b;
double L = sqrt(dx * dx + dy * dy);
if (fabs(L) > tolerance) {
LAvr += L;
LaAvr -= dx / L;
LbAvr -= dy / L;
}
}
LAvr /= N;
LaAvr /= N;
LbAvr /= N;
a = xAvr + LAvr * LaAvr;
b = yAvr + LAvr * LbAvr;
r = LAvr;
if (fabs(a - a0) <= tolerance && fabs(b - b0) <= tolerance)
break;
}
*pa = a;
*pb = b;
*pr = r;
return (j < maxIterations ? j : -1);
}
enum {
M_SHOW_CIRCLE, M_CIRCLE_INFO, M_RESET_POINTS, M_QUIT
};
但我不知道如何将我的观点和这个结合起来?? 感谢您的进阶
如果一组点是对称的,最好的方法是对 x 和 y 求和,然后您将找到中心,然后计算中心和一组点之间的平均距离,使其具有半径
这是一个圆回归问题我确定你可以问https://math.stackexchange.com/
连本站都有例子