public myPicture doSmooth(myPicture input, matrix mat) { Bitmap ret = new Bitmap(input.width, input.height); int r = mat.n / 2, s = mat.m / 2; for (int i = 0; i < input.width; ++i) { for (int j = 0; j < input.height; ++j) { double tmp = 0; for (int p = -r; p <= r; ++p) { for (int q = -s; q <= s; ++q) { tmp += 1.0 * input.getGrayDegree(i - p, j - q) * mat.a[p + r, q + s]; } } int val = (int)tmp; if (val < 0) { val = 0; } if (val > 255) { val = 255; } ret.SetPixel(i, j, Color.FromArgb(val, val, val)); } } return(new myPicture(ret, input.path)); }
public myPicture doSharp(myPicture input) { Bitmap ret = new Bitmap(input.width, input.height); for (int i = 0; i < input.width; ++i) { for (int j = 0; j < input.height; ++j) { int dx = (input.getGrayDegree(i - 1, j - 1) + 2 * input.getGrayDegree(i - 1, j) + input.getGrayDegree(i - 1, j + 1)) - (input.getGrayDegree(i + 1, j - 1) + 2 * input.getGrayDegree(i + 1, j) + input.getGrayDegree(i + 1, j + 1)); int dy = (input.getGrayDegree(i - 1, j + 1) + 2 * input.getGrayDegree(i, j + 1) + input.getGrayDegree(i + 1, j + 1)) - (input.getGrayDegree(i - 1, j - 1) + 2 * input.getGrayDegree(i, j - 1) + input.getGrayDegree(i + 1, j - 1)); if (dx < 0) { dx = -dx; } if (dy < 0) { dy = -dy; } int d = Math.Max(dx, dy); if (d > 255) { d = 255; } ret.SetPixel(i, j, Color.FromArgb(d, d, d)); } } return(new myPicture(ret, input.path)); }
//输入:原图 public getDigits(myPicture input) { int width = input.width; int height = input.height; //生成图片 Bitmap pic = new Bitmap(width, height); for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { int cur = input.grayDegree[i, j]; pic.SetPixel(i, j, Color.FromArgb(cur, cur, cur)); } } //获取文件路径和文件格式 int len = input.path.Length, pos = -1; for (int i = len - 1; i >= 0; i--) { if (input.path[i] == '.') { pos = i; } } if (pos != -1) { filePath = input.path.Substring(0, pos) + "_gray.bmp"; } else { filePath = input.path + ".bmp"; } System.Drawing.Imaging.ImageFormat imgformat = System.Drawing.Imaging.ImageFormat.Bmp; //保存图片 pic.Save(filePath, imgformat); //调用第三方软件 Process myPro = new Process(); myPro.StartInfo.FileName = "cmd.exe"; myPro.StartInfo.UseShellExecute = false; myPro.StartInfo.RedirectStandardInput = true; myPro.StartInfo.RedirectStandardOutput = true; myPro.StartInfo.RedirectStandardError = true; myPro.StartInfo.CreateNoWindow = true; myPro.Start(); textPath = filePath.Substring(0, filePath.Length - 4); string str = "tesseract " + filePath + " " + textPath + " digits"; myPro.StandardInput.WriteLine(str); myPro.StandardInput.AutoFlush = true; myPro.Close(); }
//输入:锐化和二值化后的图像,输出:找到的最大连通块,即最外层圆 public myPicture init(myPicture input) { width = input.width; height = input.height; gray = new int[width, height]; vis = new int[width, height]; //获取灰度值 for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { gray[i, j] = input.picture.GetPixel(i, j).B; vis[i, j] = 0; } } //找到最大连通块 int cou = 0, no = 1, ans = 0; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { if (vis[i, j] == 0 && gray[i, j] == 255) { cnt = 0; dfs(i, j, no); if (cou < cnt) { cou = cnt; ans = no; } no++; } } } //将最大连通块变为白色,其他区域变为黑色 Bitmap res = new Bitmap(width, height); for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { if (vis[i, j] == ans) { res.SetPixel(i, j, Color.FromArgb(255, 255, 255)); } else { res.SetPixel(i, j, Color.FromArgb(0, 0, 0)); } } } return(new myPicture(res)); }
//输入:原图和圆心信息(圆心位置和半径),输出:直线所在区域(包含较少噪声的圆环) public myPicture doFind(myPicture input, circle cir) { int width = input.width, height = input.height; Bitmap res = new Bitmap(width, height); int x = (int)cir.x, y = (int)cir.y; //截取圆环为0.15*半径——0.5*半径 int maxr = (int)(0.5 * cir.r), minr = (int)(0.15 * cir.r); for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { res.SetPixel(i, j, Color.FromArgb(255, 255, 255)); } } //将0.15*半径——0.5*半径区域赋值成原图像内容 for (int i = -maxr; i <= maxr; i++) { int pos1 = -1; for (int j = 0; j < height; j++) { if (i * i + j * j <= maxr * maxr) { pos1 = j; break; } } int pos2 = -1; for (int j = height - 1; j >= 0; j--) { if (i * i + j * j <= maxr * maxr) { pos2 = j; break; } } if (pos1 == -1) { continue; } for (int j = pos1; j <= pos2; j++) { if (i * i + j * j < minr * minr) { continue; } res.SetPixel(x + i, y + j, input.picture.GetPixel(x + i, y + j)); res.SetPixel(x + i, y - j, input.picture.GetPixel(x + i, y - j)); } } return(new myPicture(res)); }
public myPicture doSmooth(myPicture input) { Bitmap ret = new Bitmap(input.width, input.height); for (int i = 2; i + 2 < input.width; ++i) { for (int j = 2; j + 2 < input.height; ++j) { List <int> part0 = new List <int> { input.grayDegree[i - 1, j - 2], input.grayDegree[i, j - 2], input.grayDegree[i + 1, j - 2], input.grayDegree[i - 1, j - 1], input.grayDegree[i, j - 1], input.grayDegree[i + 1, j - 1], input.grayDegree[i, j] }; List <int> part1 = new List <int> { input.grayDegree[i - 1, j + 2], input.grayDegree[i, j + 2], input.grayDegree[i + 1, j + 2], input.grayDegree[i - 1, j + 1], input.grayDegree[i, j + 1], input.grayDegree[i + 1, j + 1], input.grayDegree[i, j] }; List <int> part2 = new List <int> { input.grayDegree[i - 2, j - 1], input.grayDegree[i - 2, j], input.grayDegree[i - 2, j + 1], input.grayDegree[i - 1, j - 1], input.grayDegree[i - 1, j], input.grayDegree[i - 1, j + 1], input.grayDegree[i, j] }; List <int> part3 = new List <int> { input.grayDegree[i + 2, j - 1], input.grayDegree[i + 2, j], input.grayDegree[i + 2, j + 1], input.grayDegree[i + 1, j - 1], input.grayDegree[i + 1, j], input.grayDegree[i + 1, j + 1], input.grayDegree[i, j] }; List <int> part4 = new List <int> { input.grayDegree[i - 2, j - 2], input.grayDegree[i - 2, j - 1], input.grayDegree[i - 1, j - 2], input.grayDegree[i - 1, j - 1], input.grayDegree[i - 1, j], input.grayDegree[i, j - 1], input.grayDegree[i, j] }; List <int> part5 = new List <int> { input.grayDegree[i + 2, j - 2], input.grayDegree[i + 2, j - 1], input.grayDegree[i + 1, j - 2], input.grayDegree[i + 1, j - 1], input.grayDegree[i + 1, j], input.grayDegree[i, j - 1], input.grayDegree[i, j] }; List <int> part6 = new List <int> { input.grayDegree[i + 2, j + 2], input.grayDegree[i + 2, j + 1], input.grayDegree[i + 1, j + 2], input.grayDegree[i + 1, j + 1], input.grayDegree[i + 1, j], input.grayDegree[i, j + 1], input.grayDegree[i, j] }; List <int> part7 = new List <int> { input.grayDegree[i - 2, j + 2], input.grayDegree[i - 2, j + 1], input.grayDegree[i - 1, j + 2], input.grayDegree[i - 1, j + 1], input.grayDegree[i - 1, j], input.grayDegree[i, j + 1], input.grayDegree[i, j] }; List <int> part8 = new List <int> { input.grayDegree[i - 1, j - 1], input.grayDegree[i - 1, j], input.grayDegree[i - 1, j + 1], input.grayDegree[i, j - 1], input.grayDegree[i, j], input.grayDegree[i, j + 1], input.grayDegree[i + 1, j - 1], input.grayDegree[i + 1, j], input.grayDegree[i + 1, j + 1] }; List <square> tmp = new List <square>(); tmp.Add(new square(part0)); tmp.Add(new square(part1)); tmp.Add(new square(part2)); tmp.Add(new square(part3)); tmp.Add(new square(part4)); tmp.Add(new square(part5)); tmp.Add(new square(part6)); tmp.Add(new square(part7)); tmp.Add(new square(part8)); tmp.Sort(new squareCmp()); int val = (int)tmp[0].average; ret.SetPixel(i, j, Color.FromArgb(val, val, val)); } } return(new myPicture(ret, input.path)); }
public myPicture doSharp(myPicture input) { matrix mat = new matrix(3, 3); mat.a[0, 1] = -1; mat.a[1, 0] = -1; mat.a[1, 1] = 4; mat.a[1, 2] = -1; mat.a[2, 1] = -1; smoothTemplate smooth = new smoothTemplate(); return(smooth.doSmooth(input, mat)); }
public myPicture to01Pic() { myPicture ret = this; for (int i = 0; i < width; ++i) { for (int j = 0; j < height; ++j) { int val = grayDegree[i, j]; ret.picture.SetPixel(i, j, Color.FromArgb(val, val, val)); } } return(ret); }
private void 打开ToolStripMenuItem_Click(object sender, EventArgs e) { OpenFileDialog fileName = new OpenFileDialog(); fileName.InitialDirectory = "c:\\"; fileName.FilterIndex = 2; fileName.RestoreDirectory = true; if (fileName.ShowDialog() == DialogResult.OK) { Image pic = Image.FromFile(fileName.FileName); Pic = new myPicture((Bitmap)pic, fileName.FileName); this.rawPictureDisplay.Image = Pic.picture; } }
//输入:锐化和二值化后的图像,r是擦除时使用的半径长度,x,y是圆心位置 public findTick(myPicture Pic, int r, int x, int y) { width = Pic.width; height = Pic.height; gray = new int[width, height]; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { gray[i, j] = Pic.grayDegree[i, j]; } } radius = r; circle_x = x; circle_y = y; }
public myPicture doSmooth(myPicture input) { Bitmap ret = new Bitmap(input.width, input.height); for (int i = 0; i < input.width; ++i) { for (int j = 0; j < input.height; ++j) { List <pair> tmp = new List <pair>(); for (int ii = 0; ii < 5; ++ii) { for (int jj = 0; jj < 5; ++jj) { int ni = i + dx[ii]; int nj = j + dy[jj]; if (ni == i && nj == j) { continue; } if (ni < 0 || ni >= input.width) { continue; } if (nj < 0 || nj >= input.height) { continue; } int d = input.grayDegree[ni, nj] - input.grayDegree[i, j]; if (d < 0) { d = -d; } tmp.Add(new pair(d, input.grayDegree[ni, nj])); } } tmp.Sort(new pairCmp()); int sum = 0; for (int k = 0; k < 5; ++k) { sum += tmp[k].y; } sum /= 5; ret.SetPixel(i, j, Color.FromArgb(sum, sum, sum)); } } return(new myPicture(ret, input.path)); }
//输入:锐化和二值化后的图像,r是找到的圆环半径,x,y是圆心位置 public eraseCircleElement(myPicture Pic, int r, int x, int y) { width = Pic.width; height = Pic.height; gray = new int[width, height]; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { gray[i, j] = Pic.grayDegree[i, j]; } } res = new Bitmap(width, height); radius = r; circle_x = x; circle_y = y; }
//输入:对最大连通块锐化后的图像,即变成两个同心圆,输出:内层圆 public myPicture doHough(myPicture input) { int width = input.width, height = input.height; Bitmap res = new Bitmap(width, height); int sx = width / 2, sy = height / 2; //找到内层圆上的一个像素点 for (int i = sx; i >= 0; i--) { if (input.grayDegree[i, sy] == 255) { sx = i; break; } } //初始化 gray = new int[width, height]; vis = new int[width, height]; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { gray[i, j] = input.grayDegree[i, j]; vis[i, j] = 0; } } //dfs找内层圆 dfs(sx, sy, 1); //修改图像 for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { if (vis[i, j] == 1) { res.SetPixel(i, j, Color.FromArgb(255, 255, 255)); } else { res.SetPixel(i, j, Color.FromArgb(0, 0, 0)); } } } return(new myPicture(res)); }
public myPicture doSmooth(myPicture input) { Bitmap ret = new Bitmap(input.width, input.height); for (int i = 0; i < input.width; ++i) { for (int j = 0; j < input.height; ++j) { int cnt = 0; List <int> tmp = new List <int>(); for (int ii = 0; ii < 3; ++ii) { for (int jj = 0; jj < 3; ++jj) { int ni = i + dx[ii]; int nj = j + dy[jj]; if (ni == i && nj == j) { continue; } if (ni < 0 || ni >= input.width) { continue; } if (nj < 0 || nj >= input.height) { continue; } ++cnt; tmp.Add(input.grayDegree[ni, nj]); } } tmp.Sort(); int val = tmp[cnt / 2]; ret.SetPixel(i, j, Color.FromArgb(val, val, val)); } } return(new myPicture(ret, input.path)); }
public myPicture doSmooth(myPicture input) { Bitmap ret = new Bitmap(input.width, input.height); for (int i = 0; i < input.width; ++i) { for (int j = 0; j < input.height; ++j) { int cnt = 0; int sum = 0; for (int ii = 0; ii < 3; ++ii) { for (int jj = 0; jj < 3; ++jj) { int ni = i + dx[ii]; int nj = j + dy[jj]; if (ni == i && nj == j) { continue; } if (ni < 0 || ni >= input.width) { continue; } if (nj < 0 || nj >= input.height) { continue; } ++cnt; sum += input.grayDegree[ni, nj]; } } sum /= cnt; ret.SetPixel(i, j, Color.FromArgb(sum, sum, sum)); } } return(new myPicture(ret, input.path)); }
public myPicture doSharp(myPicture input) { Bitmap ret = new Bitmap(input.width, input.height); for (int i = 0; i < input.width; ++i) { for (int j = 0; j < input.height; ++j) { int d1 = input.getGrayDegree(i, j) - input.getGrayDegree(i - 1, j - 1); int d2 = input.getGrayDegree(i, j) - input.getGrayDegree(i + 1, j - 1); if (d1 < 0) { d1 = -d1; } if (d2 < 0) { d2 = -d2; } int d = Math.Max(d1, d2); ret.SetPixel(i, j, Color.FromArgb(d, d, d)); } } return(new myPicture(ret, input.path)); }
public myPicture doSharp(myPicture input) { Bitmap ret = new Bitmap(input.width, input.height); for (int i = 0; i < input.width; ++i) { for (int j = 0; j < input.height; ++j) { int val1 = -5 * input.getGrayDegree(i - 1, j - 1) + 3 * input.getGrayDegree(i - 1, j) + 3 * input.getGrayDegree(i - 1, j + 1) - 5 * input.getGrayDegree(i, j - 1) + 3 * input.getGrayDegree(i, j + 1) - 5 * input.getGrayDegree(i + 1, j - 1) + 3 * input.getGrayDegree(i + 1, j) + 3 * input.getGrayDegree(i + 1, j + 1); int val2 = +3 * input.getGrayDegree(i - 1, j - 1) + 3 * input.getGrayDegree(i - 1, j) + 3 * input.getGrayDegree(i - 1, j + 1) - 5 * input.getGrayDegree(i, j - 1) + 3 * input.getGrayDegree(i, j + 1) - 5 * input.getGrayDegree(i + 1, j - 1) - 5 * input.getGrayDegree(i + 1, j) + 3 * input.getGrayDegree(i + 1, j + 1); int val3 = +3 * input.getGrayDegree(i - 1, j - 1) + 3 * input.getGrayDegree(i - 1, j) + 3 * input.getGrayDegree(i - 1, j + 1) + 3 * input.getGrayDegree(i, j - 1) + 3 * input.getGrayDegree(i, j + 1) - 5 * input.getGrayDegree(i + 1, j - 1) - 5 * input.getGrayDegree(i + 1, j) - 5 * input.getGrayDegree(i + 1, j + 1); int val4 = +3 * input.getGrayDegree(i - 1, j - 1) + 3 * input.getGrayDegree(i - 1, j) + 3 * input.getGrayDegree(i - 1, j + 1) + 3 * input.getGrayDegree(i, j - 1) - 5 * input.getGrayDegree(i, j + 1) + 3 * input.getGrayDegree(i + 1, j - 1) - 5 * input.getGrayDegree(i + 1, j) - 5 * input.getGrayDegree(i + 1, j + 1); int val5 = +3 * input.getGrayDegree(i - 1, j - 1) + 3 * input.getGrayDegree(i - 1, j) - 5 * input.getGrayDegree(i - 1, j + 1) + 3 * input.getGrayDegree(i, j - 1) - 5 * input.getGrayDegree(i, j + 1) + 3 * input.getGrayDegree(i + 1, j - 1) + 3 * input.getGrayDegree(i + 1, j) - 5 * input.getGrayDegree(i + 1, j + 1); int val6 = +3 * input.getGrayDegree(i - 1, j - 1) - 5 * input.getGrayDegree(i - 1, j) - 5 * input.getGrayDegree(i - 1, j + 1) + 3 * input.getGrayDegree(i, j - 1) - 5 * input.getGrayDegree(i, j + 1) + 3 * input.getGrayDegree(i + 1, j - 1) + 3 * input.getGrayDegree(i + 1, j) + 3 * input.getGrayDegree(i + 1, j + 1); int val7 = -5 * input.getGrayDegree(i - 1, j - 1) - 5 * input.getGrayDegree(i - 1, j) - 5 * input.getGrayDegree(i - 1, j + 1) + 3 * input.getGrayDegree(i, j - 1) + 3 * input.getGrayDegree(i, j + 1) + 3 * input.getGrayDegree(i + 1, j - 1) + 3 * input.getGrayDegree(i + 1, j) + 3 * input.getGrayDegree(i + 1, j + 1); int val8 = -5 * input.getGrayDegree(i - 1, j - 1) - 5 * input.getGrayDegree(i - 1, j) + 3 * input.getGrayDegree(i - 1, j + 1) - 5 * input.getGrayDegree(i, j - 1) + 3 * input.getGrayDegree(i, j + 1) + 3 * input.getGrayDegree(i + 1, j - 1) + 3 * input.getGrayDegree(i + 1, j) + 3 * input.getGrayDegree(i + 1, j + 1); int val = 0; if (val1 < 0) { val1 = -val1; } if (val2 < 0) { val2 = -val2; } if (val3 < 0) { val3 = -val3; } if (val4 < 0) { val4 = -val4; } if (val5 < 0) { val5 = -val5; } if (val6 < 0) { val6 = -val6; } if (val7 < 0) { val7 = -val7; } if (val8 < 0) { val8 = -val8; } if (val1 > val) { val = val1; } if (val2 > val) { val = val2; } if (val3 > val) { val = val3; } if (val4 > val) { val = val4; } if (val5 > val) { val = val5; } if (val6 > val) { val = val6; } if (val7 > val) { val = val7; } if (val8 > val) { val = val8; } if (val > 255) { val = 255; } ret.SetPixel(i, j, Color.FromArgb(val, val, val)); } } return(new myPicture(ret, input.path)); }
//利用OTSU算法实现二值化 //输入:input为灰度图像 //输出:res为二值图像 //选取的阈值使分割出的两类像素,类间方差最大,类内方差最小 public myPicture doOTSU(myPicture input) { Bitmap res = new Bitmap(input.width, input.height); int [,,] count = new int[40, 40, 256]; int MAGIC = 300; for (int i = 0; i < input.width; ++i) { for (int j = 0; j < input.height; ++j) { count[i / MAGIC, j / MAGIC, input.grayDegree[i, j]]++; } } for (int i = 0; i < input.width; i += MAGIC) { for (int j = 0; j < input.height; j += MAGIC) { int ii = i / MAGIC; int jj = j / MAGIC; double n1, n2, n, sum1, sum2, sum; n1 = 0; n = 0; sum1 = 0; sum = 0; for (int t = 0; t < 256; ++t) { int val = count[ii, jj, t]; sum += 1.0 * t * val; n += val; } double maxVal = -1.0; int threshold = -1; for (int t = 0; t < 256; ++t) { int val = count[ii, jj, t]; n1 += val; if (n1 == 0) { continue; } n2 = n - n1; if (n2 == 0) { break; } sum1 += 1.0 * t * val; sum2 = sum - sum1; double m1 = sum1 / n1; double m2 = sum2 / n2; double tmp = n1 * n2 * (m1 - m2) * (m1 - m2); if (tmp > maxVal) { maxVal = tmp; threshold = t; } } for (int p = i; p < Math.Min(i + MAGIC, input.width); ++p) { for (int q = 0; q < Math.Min(j + MAGIC, input.height); ++q) { if (input.grayDegree[p, q] <= threshold) { res.SetPixel(p, q, Color.FromArgb(0, 0, 0)); } else { res.SetPixel(p, q, Color.FromArgb(255, 255, 255)); } } } } } return(new myPicture(res)); }
//计算圆的圆心,输入为自定义图片类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)); }
public inPut(myPicture _Pic) { Pic = _Pic; InitializeComponent(); }
//函数功能:对main.cs传入的图像进行处理,并将结果传递到ans.cs显示 public void domain() { //处理输入 double low = 0.0; double high = 1.0; try { low = Convert.ToDouble(smallInput.Text); high = Convert.ToDouble(largeInput.Text); } catch { return; } OTSU B = new OTSU(); //锐化、二值化 myPicture ret = B.doOTSU(sharp4.doSharp(Pic)); myPicture res = ret; //找圆心之前的预处理 findCircleInit circle = new findCircleInit(); ret = circle.init(ret); ret = sharp4.doSharp(ret); ret = circle.doHough(ret); //找圆心 circle o = new findCircleCenter().doFind(ret); //找指针 ret = new findLineInit().doFind(Pic, o); myPicture tmp = sharp1.doSharp(ret); tmp = smooth2.doSmooth(tmp); tmp = B.doOTSU(tmp); RANSAC R = new RANSAC(); myPair L = R.doFind(smooth2.doSmooth(B.doOTSU(sharp4.doSharp(Pic))), R.doRANSAC(tmp, new myPair((int)o.x, (int)o.y)), o); //找刻度线的预处理 eraseCircleElement ECE = new eraseCircleElement(res, (int)o.r, (int)o.x, (int)o.y); int r = ECE.solve(); res = ECE.erase(r - 1); //找到左右两端的刻度线 findTick ticks = new findTick(res, r - 1, (int)o.x, (int)o.y); myPair left = ticks.FindLeft(), right = ticks.FindRight(); //求角度 double thta = 2 * Math.PI - angle(left, right, o); double alpha; if (L.x <= o.x) { alpha = angle(left, L, o); } else { alpha = thta - angle(L, right, o); } double ans = low + (high - low) * (alpha + Math.PI / 180) / thta; Form newForm = new ans(ans); newForm.ShowDialog(); newForm.Dispose(); }
//函数功能:确定仪表盘指针的方向向量 //输入:二值图像input,直线方程ret,仪表盘中心o //输出:仪表盘指针上的某一个点 public myPair doFind(myPicture input, line ret, circle o) { if (Math.Abs(ret.B) < 0.000001) { return(new myPair((int)o.x, 0)); } int MAGIC = (int)(input.width * 0.18); int cnt1 = 0, cnt2 = 0; double K = -ret.A / ret.B; double B = -ret.C / ret.B; for (int dx = 1; dx <= MAGIC; ++dx) { double x = o.x + dx; double y = K * x + B; int xx = (int)x; int yy = (int)y; if (xx + 2 >= input.width || xx - 2 < 0) { break; } if (yy + 2 >= input.height || yy - 2 < 0) { break; } for (int i = -2; i <= 2; ++i) { for (int j = -2; j <= 2; ++j) { if (input.grayDegree[(int)(x + i), (int)(y + j)] == 255) { cnt1++; } } } } for (int dx = 1; dx <= MAGIC; ++dx) { double x = o.x - dx; double y = K * x + B; int xx = (int)x; int yy = (int)y; if (xx + 2 >= input.width || xx - 2 < 0) { break; } if (yy + 2 >= input.height || yy - 2 < 0) { break; } for (int i = -2; i <= 2; ++i) { for (int j = -2; j <= 2; ++j) { if (input.grayDegree[(int)(x + i), (int)(y + j)] == 255) { cnt2++; } } } } if (cnt1 > cnt2) { double x = o.x + MAGIC; double y = K * x + B; return(new myPair((int)x, (int)y)); } else { double x = o.x - MAGIC; double y = K * x + B; return(new myPair((int)x, (int)y)); } }
//函数功能:利用RANSAC算法从图像中提取直线,RANSAC对噪声敏感度小 //输入:二值化图像input,目标直线的一个端点center //输出:目标直线方程 public line doRANSAC(myPicture input, myPair center) { LinkedList <myPair> arr = new LinkedList <myPair>(); for (int i = 0; i < input.width; ++i) { for (int j = 0; j < input.height; ++j) { if (input.grayDegree[i, j] == 255) { arr.AddLast(new myPair(i, j)); } } } Random rd = new Random(13); line ret = new line(0, 0, 0); double besterror = 1000000000000; int bound = (int)(0.07 * arr.Count); for (int iter = 0; iter < 100; ++iter) { int sampleIndex = rd.Next() % arr.Count; myPair sample = arr.ElementAt(sampleIndex); line cur = new line(center, sample); LinkedList <myPair> alsoinliers = new LinkedList <myPair>(); foreach (myPair p in arr) { double d = cur.distance(p); if (d <= 4) { alsoinliers.AddLast(p); } } if (alsoinliers.Count >= bound) { alsoinliers.AddLast(sample); line better = calLine(alsoinliers); double thiserror = 0; foreach (myPair p in alsoinliers) { double dis = better.distance(p); thiserror += dis * dis; } thiserror /= alsoinliers.Count; if (thiserror < besterror) { besterror = thiserror; ret = better; } } } return(ret); /* * for (int i = 0; i < input.width; ++i) * { * for (int j = 0; j < input.height; ++j) * { * double val = Math.Abs(ret.A * i + ret.B * j + ret.C); * if (val <= 1) * { * input.picture.SetPixel(i, j, Color.FromArgb(255, 0, 0)); * } * } * } */ //return input; }