//程序功能:利用最小二乘法拟合直线 //输入:二维点 //输出:拟合直线 line calLine(LinkedList <myPair> input) { matrix A = new matrix(input.Count, 2); matrix AT = new matrix(2, input.Count); matrix B = new matrix(input.Count, 1); for (int i = 0; i < input.Count; ++i) { myPair cur = input.ElementAt(i); A.a[i, 0] = cur.x; A.a[i, 1] = cur.y; AT.a[0, i] = cur.x; AT.a[1, i] = cur.y; B.a[i, 0] = 100; } matrix coef = AT.doMul(A); matrix b = AT.doMul(B); matrix mat = new matrix(2, 3); for (int i = 0; i < 2; ++i) { for (int j = 0; j < 2; ++j) { mat.a[i, j] = coef.a[i, j]; } } mat.a[0, 2] = b.a[0, 0]; mat.a[1, 2] = b.a[1, 0]; double BB = (mat.a[0, 0] * mat.a[1, 2] - mat.a[1, 0] * mat.a[0, 2]) / (mat.a[1, 1] * mat.a[0, 0] - mat.a[0, 1] * mat.a[1, 0]); double AA = (mat.a[0, 2] - mat.a[0, 1] * BB) / mat.a[0, 0]; return(new line(AA, BB, -100)); }
//计算圆的圆心,输入为自定义图片类input,输出为三元组(x,y,r) //对input的限制:只包含单圆环 public circle doFind(myPicture input) { //从圆周上对称取10组点 int cnt = 0; LinkedList <myPair> arr = new LinkedList <myPair>(); for (int i = 2; i < input.width; i += 8) { for (int j = 5; j < input.height; ++j) { if (input.grayDegree[i, j] == 255) { cnt++; arr.AddLast(new myPair(i, j)); for (int k = input.height - 5; k >= 0; --k) { if (input.grayDegree[i, k] == 255) { arr.AddLast(new myPair(i, k)); break; } } break; } } if (cnt == 10) { break; } } //最小二乘法求解圆心 A = new matrix(2 * cnt, 3); AT = new matrix(3, 2 * cnt); B = new matrix(2 * cnt, 1); int cur = 0; foreach (myPair p in arr) { int x = p.x; int y = p.y; A.a[cur, 0] = x; A.a[cur, 1] = y; A.a[cur, 2] = 1; AT.a[0, cur] = x; AT.a[1, cur] = y; AT.a[2, cur] = 1; B.a[cur, 0] = 1.0 * x * x + 1.0 * y * y; cur++; } matrix coef = AT.doMul(A); matrix b = AT.doMul(B); matrix mat = new matrix(3, 4); for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { mat.a[i, j] = coef.a[i, j]; } } mat.a[0, 3] = b.a[0, 0]; mat.a[1, 3] = b.a[1, 0]; mat.a[2, 3] = b.a[2, 0]; return(cal(mat)); }