public override void Recycle() { base.Recycle(); t = 0; speed = 4; recycleTimer.Restart(); }
public void Tick() { if (curCount == count) { Fire(); count--; } timer.Tick(); if (timer.state == MyTimer.STATE.finished && count != 0) { Fire(); if (count != -1) { count--; } timer.Restart(); } }
private static void fastPruningWithRSC() { int s = 100, r = 5; MyTimer timer = new MyTimer(); string[] templatefiles = Directory.GetFiles(@"D:\Play Data\train_data\sc\", "*.sc") .Take(1000).ToArray(); #region 打开模板 string templatepath = @"D:\Play Data\template\"; int templatecount = templatefiles.Length; Debug("打开{0}个模板--------------------------------------------", templatecount); double[][,] templates = new double[templatecount][,]; int[] templatenums = new int[templatecount]; timer.Restart(); for (int i = 0; i < templatefiles.Length; ++i) { string file = templatefiles[i]; string filename = Path.GetFileNameWithoutExtension(file); templatenums[i] = int.Parse(filename.Split('-')[1]); templates[i] = new double[s, 60]; unsafe { #region 指针也快不了多少 //byte[] data = File.ReadAllBytes(file); //fixed (byte* ptr = data) { // //using (var fs = new FileStream(file, FileMode.Open)) { // // using (var br = new BinaryReader(fs)) { // int offset = 0; // for (int j = 0; j < s; ++j) { // for (int k = 0; k < 60; ++k) { // //templates[i][j, k] = br.ReadDouble(); // fixed (double* t = &templates[i][j, k]) { // for (int p = 0; p < sizeof(double); ++p) // *((byte*)t + p) = *(ptr + offset++); // } // } // } //} #endregion using (var fs = new FileStream(file, FileMode.Open)) { using (var br = new BinaryReader(fs)) { for (int j = 0; j < s; ++j) { for (int k = 0; k < 60; ++k) { templates[i][j, k] = br.ReadDouble(); } } } } } if (i % 100 == 0) Debug("已完成{0}个", i); } Debug("模板读取完成,用时{0}ms.", timer.Stop()); #endregion string[] testfiles = Directory.GetFiles(@"D:\Play Data\test\", "*.bmp") .Take(100).ToArray(); #region 测试 int testcase = testfiles.Length, acc = 0; Debug("为{0}个对象寻找候选模板------------------------------------------", testcase); foreach (var file in testfiles) { timer.Restart(); string filenameext = Path.GetFileName(file); string filename = Path.GetFileNameWithoutExtension(file); int thisnum = int.Parse(filename.Split('-')[1]); Image<Gray, Byte> img = new Image<Gray, byte>(file); var list = getEdge(img.Resize(2.5, Emgu.CV.CvEnum.INTER.CV_INTER_LINEAR)).Sample(s); var sc100 = Jim.OCR.ShapeContext2D.ShapeContext.ComputeSC(list); double[,] scq = new double[r, 60]; for (int i = 0; i < 5; ++i) { int pos = rand.Next(s); for (int k = 0; k < 60; ++k) { scq[i, k] = sc100[pos, k]; } } var arr = new ValueIndexPair<double>[templatecount]; for (int i = 0; i < templatecount; ++i) { double[,] sci = templates[i]; double[,] costmat = Jim.OCR.ShapeContext2D.ShapeContext.HistCost(scq, sci); double cost = 0; for (int j = 0; j < 5; ++j) { double min = double.MaxValue; for (int u = 0; u < s; ++u) { double val = costmat[j, u]; if (val < min) min = val; } cost += min; } arr[i] = new ValueIndexPair<double> { Value = cost, Index = i }; } Array.Sort(arr, (a, b) => a.Value.CompareTo(b.Value)); int[] matchcount = new int[10]; double[] matchcost = new double[10]; int knn = 10; foreach (var pair in arr.Take(knn)) { int num = templatenums[pair.Index]; matchcount[num]++; matchcost[num] += pair.Value; } var match = matchcount.Select((val, i) => new { Count = val, Num = i }) .Where(v => v.Count > 0) .OrderByDescending(v => v.Count).ToArray(); //var match = matchcost.Select((val, i) => new { Cost = val / matchcount[i], Num = i }) // .Where(v => !double.IsNaN(v.Cost)) // .OrderBy(v => v.Cost).ToArray(); #region 进行精细匹配,效果一般 //double[] matchrate = new double[10]; //foreach (var m in match) { // if (m.Count == 0) break; // string template = Path.Combine(templatepath, m.Num + ".bmp"); // Jim.OCR.ShapeContext2D.ShapeContext sc = new Jim.OCR.ShapeContext2D.ShapeContext(file, template); // sc.debug_flag = false; // sc.timer_flag = false; // sc.display_flag = false; // sc.n_iter = 3; // sc.matchScale = 2.5; // sc.maxsamplecount = 100; // matchrate[m.Num] = sc.MatchFile(); //} //var bestmatches = matchrate.Select((val, i) => new { Cost = val, Num = i }) // .Where(m => m.Cost > 0) // .OrderBy(m => m.Cost).ToArray(); //int firstmatch = bestmatches[0].Num; #endregion int firstmatch = match[0].Num; var fc = Console.ForegroundColor; Console.ForegroundColor = firstmatch == thisnum ? ConsoleColor.Green : ConsoleColor.Red; string info = String.Format("{0} {1}ms - {2}\t", filename, timer.Stop(), (firstmatch == thisnum ? "Right" : "Wrong")); //foreach (var m in bestmatches.Take(4)) { foreach (var m in match) { info += String.Format("{0}/{1}\t", m.Num, m.Count); //info += String.Format("{0}/{1:F3}\t", m.Num, m.Cost); //info += String.Format("{0}/{1:F3}\t", m.Num, m.Cost); } Debug(info); Console.ForegroundColor = fc; if (firstmatch == thisnum) { ++acc; } } Debug("测试用例:{0}。正确率{1}。", testcase, acc); #endregion }
private static ImageShapeContext CreateShapeContext(string path, string fontFamily, int samplecount, char c) { MyTimer timer = new MyTimer(); Font font = new Font(fontFamily, 240); string file = Path.Combine(path, String.Format("{0}-{1}.bmp", fontFamily, c)); string fontpath = Path.Combine(path, fontFamily); Image<Bgr, Byte> img = new Image<Bgr, byte>(400, 400); using (Graphics g = Graphics.FromImage(img.Bitmap)) { g.Clear(Color.Black); g.DrawString(c.ToString(), font, Brushes.White, 0, 0); } timer.Restart(); var canny = img.Convert<Gray, Byte>().Canny(new Gray(100), new Gray(60)); timer.StopAndSay("Canny"); timer.Restart(); List<Point> edge = new List<Point>(); for (int y = 0; y < canny.Height; ++y) { for (int x = 0; x < canny.Width; ++x) { if (canny[y, x].Intensity > 0) { edge.Add(new Point(x, y)); } } } var sample = edge.Sample(samplecount); timer.StopAndSay("Sample"); using (var sw = new StreamWriter(Path.Combine(path, String.Format("!Sample-{0}-{1}.txt", fontFamily, c)))) { foreach (var p in sample) { sw.WriteLine("{0},{1}", p.X, p.Y); } } timer.Restart(); double min, max; var norm = Jim.OCR.Algorithms.ShapeContext.Normalize(sample, out min, out max); timer.StopAndSay("Normalize"); timer.Restart(); var scs = new ImageShapeContext(sample); for (int i = 0; i < norm.Length; ++i) { scs.ShapeContests[i] = new Jim.OCR.Algorithms.ShapeContext(norm[i]); //var his = sc.Histogram.ToImage(); var p = sample[i]; //string hisfile = Path.Combine(fontpath, string.Format("[{0},{1}].bmp", p.X, p.Y)); //his.Save(hisfile); img[p] = new Bgr(0, 0, 255); } timer.StopAndSay("ShapeContext"); //foreach (var p in sample) { // var sc = new ShapeContext(p, sample); // var his = sc.Histogram.ToImage(); // string hisfile = Path.Combine(fontpath, string.Format("[{0},{1}].bmp", p.X, p.Y)); // his.Save(hisfile); // img[p] = new Bgr(0, 0, 255); //} //var contours = img.Convert<Gray, Byte>().FindContours(); //img.Draw(contours, new Bgr(0, 0, 255), new Bgr(0, 255, 0), 2, 1); //dfsContour(img, contours, 0, 2); //foreach (var ii in contours.) { // //Console.WriteLine // img[ii] = new Bgr(0, 0, 255); //} //img.Save(file); return scs; }
private static void computeTemplateSC(int start, int count) { int s = 100; string[] templatefiles = Directory.GetFiles(@"D:\Play Data\my_template\", "*.jpg") .Skip(start).Take(count).ToArray(); int templatecount = templatefiles.Length; Debug("解析{0}个模板--------------------------------------------", templatecount); MyTimer timer = new MyTimer(); timer.Restart(); for (int i = 0; i < templatecount; ++i) { string file = templatefiles[i]; string filenameext = Path.GetFileName(file); string filename = Path.GetFileNameWithoutExtension(file); Image<Gray, Byte> img = new Image<Gray, byte>(file); var list = getEdge(img.Resize(2.5, Emgu.CV.CvEnum.INTER.CV_INTER_LINEAR)).Sample(s); if (i % 100 == 0) Debug("已完成{0}个", i); var sc = Jim.OCR.ShapeContext2D.ShapeContext.ComputeSC(list); using (var fs = new FileStream(Path.Combine(@"D:\Play Data\my_template_data\sc\", filename + ".sc"), FileMode.Create)) { using (var bw = new BinaryWriter(fs)) { for (int j = 0; j < s; ++j) { for (int k = 0; k < 60; ++k) { bw.Write(sc[j, k]); } } } } } Debug("模板计算完成,用时{0}ms.", timer.Stop()); }
private static void clusterSC() { int s = 100, K = 100; string[] templatefiles = Directory.GetFiles(@"D:\Play Data\my_template_data\sc\", "*.sc") .Take(180).ToArray(); int templatecount = templatefiles.Length; #region 读取模板 Debug("打开{0}个模板--------------------------------------------", templatecount); double[][] templates = new double[templatecount * s][]; MyTimer timer = new MyTimer(); timer.Restart(); for (int i = 0; i < templatefiles.Length; ++i) { string file = templatefiles[i]; string filename = Path.GetFileNameWithoutExtension(file); using (var fs = new FileStream(file, FileMode.Open)) { using (var br = new BinaryReader(fs)) { for (int j = 0; j < s; ++j) { templates[i * s + j] = new double[60]; for (int k = 0; k < 60; ++k) { templates[i * s + j][k] = br.ReadDouble(); } } } } if (i % 100 == 0) Debug("已完成{0}个", i); } Debug("模板读取完成,用时{0}ms.", timer.Stop()); #endregion #region 聚类 timer.Restart(); KMeans<double[]> kmeans = new KMeans<double[]>(templates, K, Jim.OCR.ShapeContext2D.ShapeContext.HistCost, scs => { double[] scnew = new double[60]; for (int k = 0; k < 60; ++k) { scnew[k] = scs.Average(sc => sc[k]); } return scnew; } ); kmeans.MaxIterate = 100; var cluster = kmeans.Cluster(); Debug("聚类完成,用时{0}ms.", timer.Stop()); #endregion using (var fs = new FileStream(Path.Combine(@"D:\Play Data\my_template_data\sm-" + K, templatecount + ".sm"), FileMode.Create)) { using (var bw = new BinaryWriter(fs)) { for (int i = 0; i < K; ++i) { for (int k = 0; k < 60; ++k) { bw.Write(cluster[i].Center[k]); } } } } }
private static void testMNIST2() { List<string> wrong = new List<string>(); int testcount = 100, pos = 0; MyTimer timer = new MyTimer(); foreach (var file in Directory.GetFiles(@"D:\Play Data\test", "*.bmp")) { if (pos == testcount) break; string filename = Path.GetFileNameWithoutExtension(file); int ans = int.Parse(filename.Split('-')[1]); timer.Restart(); double[] results = new double[10]; int scale = 8; for (int d = 0; d < 10; ++d) { string template = Path.Combine(@"D:\Play Data\template", d + ".bmp"); var sc = new Jim.OCR.ShapeContext2D.ShapeContext(file, template); sc.n_iter = 1; //sc.showScale = 6; sc.matchScale = 2.5; sc.maxsamplecount = 100; sc.display_flag = false; sc.debug_flag = false; sc.timer_flag = false; double matchcost = sc.MatchFile(); results[d] = matchcost;// / sc.nsamp; } var sort = results.Select((c, i) => new { Cost = c, Digit = i }).OrderBy(v => v.Cost).ToArray(); if (sort[0].Digit == ans) { var fc = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.Green; string s = String.Format("File:{0}-{1}ms-Right!\t", filename, timer.Stop()); for (int i = 0; i < 4; ++i) { s += String.Format("{0}/{1:F4}, ", sort[i].Digit, sort[i].Cost); } Debug(s); Console.ForegroundColor = fc; } else { var fc = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.Red; //Debug("File:{0}-{1}ms-Opps!", filename, Timer.Stop()); wrong.Add(filename); string s = String.Format("File:{0}-{1}ms-Wrong!\t", filename, timer.Stop()); for (int i = 0; i < 4; ++i) { s += String.Format("{0}/{1:F4}, ", sort[i].Digit, sort[i].Cost); } Debug(s); Console.ForegroundColor = fc; #region 画对比图 //string dir = Path.Combine(@"D:\Play Data\output", filename); //if (Directory.Exists(dir)) Directory.Delete(dir, true); //Directory.CreateDirectory(dir); //for (int d = 0; d < 10; ++d) { // var sc = isc1[d]; // var sci = isc2[d]; // var km = kms[d]; // int ax = (int)sc.Points.Average(p => p.X), // ay = (int)sc.Points.Average(p => p.Y), // bx = (int)sci.Points.Average(p => p.X), // by = (int)sci.Points.Average(p => p.Y); // int dx = bx - ax, // dy = by - ay; // Image<Bgr, Byte> img = new Image<Bgr, byte>(28 * scale, 28 * scale); // Font fs = new Font("Arial", 18); // using (Graphics g = Graphics.FromImage(img.Bitmap)) { // g.Clear(Color.Black); // for (int j = 0; j < sci.Points.Count; ++j) { // int i = km.MatchPair[j + sc.Points.Count]; // Point pb = sci.Points[j], pa = sc.Points[i]; // pb.X -= dx; // pb.Y -= dy; // int r = 2; // g.DrawEllipse(Pens.Red, pa.X * scale - r, pa.Y * scale - r, r * 2 + 1, r * 2 + 1); // g.DrawEllipse(Pens.Green, pb.X * scale - r, pb.Y * scale - r, r * 2 + 1, r * 2 + 1); // g.DrawLine(Pens.Gray, new Point(pa.X * scale, pa.Y * scale), new Point(pb.X * scale, pb.Y * scale)); // } // g.DrawString(results[d].ToString(), fs, Brushes.White, new PointF(0, 0)); // } // img.Save(Path.Combine(dir, d + ".bmp")); //} #endregion } ++pos; } Debug("Wrong:{0}", wrong.Count); Debug("Wrong rate:{0:F2}%", 100.0 * wrong.Count / testcount); }
private static void testMNIST() { var timer = new MyTimer(); List<Point>[] Edges = new List<Point>[10]; #region 准备边缘集合 //Font standardFont = new Font("Arial", 20); //for (int i = 0; i < 10; ++i) { // Image<Bgr, Byte> img = new Image<Bgr, byte>(28, 28); // using (Graphics g = Graphics.FromImage(img.Bitmap)) { // g.Clear(Color.Black); // g.DrawString(i.ToString(), standardFont, Brushes.White, 0, 0); // } // Edges[i] = getEdge(img.Convert<Gray, Byte>()); // //img.Save(Path.Combine(@"D:\Play Data\", i + ".bmp")); //} for (int i = 0; i < 10; ++i) { string template = Path.Combine(@"D:\Play Data\template", i + ".bmp"); Image<Gray, Byte> img = new Image<Gray, byte>(template); Edges[i] = getEdge(img); } #endregion List<string> wrong = new List<string>(); int testcount = 100, pos = 0; foreach (var file in Directory.GetFiles(@"D:\Play Data\test", "*.bmp")) { if (pos == testcount) break; string filename = Path.GetFileNameWithoutExtension(file); int ans = int.Parse(filename.Split('-')[1]); timer.Restart(); List<Point> edge = getEdge(new Image<Gray, byte>(file)); ImageShapeContext[] isc1 = new ImageShapeContext[10]; ImageShapeContext[] isc2 = new ImageShapeContext[10]; KM[] kms = new KM[10]; double[] results = new double[10]; int scale = 8; for (int d = 0; d < 10; ++d) { int samplecount = Math.Min(edge.Count, Edges[d].Count); var sc = createISC(edge, samplecount); var sci = createISC(Edges[d], samplecount); var scm = new ShapeContextMatching(sc.ShapeContests, sci.ShapeContests); scm.BuildCostGraph(); var km = scm.Match(); isc1[d] = sc; isc2[d] = sci; kms[d] = km; results[d] = (double)km.MatchResult / samplecount; } var sort = results.Select((c, i) => new { Cost = c, Digit = i }).OrderBy(v => v.Cost).ToArray(); if (sort[0].Digit == ans) { var fc = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.Green; string s = String.Format("File:{0}-{1}ms-Right!\t", filename, timer.Stop()); for (int i = 0; i < 4; ++i) { s += String.Format("{0}/{1:F4}, ", sort[i].Digit, sort[i].Cost); } Debug(s); Console.ForegroundColor = fc; } else { var fc = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.Red; wrong.Add(filename); string s = String.Format("File:{0}-{1}ms-Wrong!", filename, timer.Stop()); for (int i = 0; i < 5; ++i) { s += String.Format("{0}/{1:F2}, ", sort[i].Digit, sort[i].Cost); } Debug(s); Console.ForegroundColor = fc; string dir = Path.Combine(@"D:\Play Data\output", filename); if (Directory.Exists(dir)) Directory.Delete(dir, true); Directory.CreateDirectory(dir); for (int d = 0; d < 10; ++d) { var sc = isc1[d]; var sci = isc2[d]; var km = kms[d]; int ax = (int)sc.Points.Average(p => p.X), ay = (int)sc.Points.Average(p => p.Y), bx = (int)sci.Points.Average(p => p.X), by = (int)sci.Points.Average(p => p.Y); int dx = bx - ax, dy = by - ay; Image<Bgr, Byte> img = new Image<Bgr, byte>(28 * scale, 28 * scale); Font fs = new Font("Arial", 18); using (Graphics g = Graphics.FromImage(img.Bitmap)) { g.Clear(Color.Black); for (int j = 0; j < sci.Points.Count; ++j) { int i = km.MatchPair[j + sc.Points.Count]; Point pb = sci.Points[j], pa = sc.Points[i]; pb.X -= dx; pb.Y -= dy; int r = 2; g.DrawEllipse(Pens.Red, pa.X * scale - r, pa.Y * scale - r, r * 2 + 1, r * 2 + 1); g.DrawEllipse(Pens.Green, pb.X * scale - r, pb.Y * scale - r, r * 2 + 1, r * 2 + 1); g.DrawLine(Pens.Gray, new Point(pa.X * scale, pa.Y * scale), new Point(pb.X * scale, pb.Y * scale)); } g.DrawString(results[d].ToString(), fs, Brushes.White, new PointF(0, 0)); } img.Save(Path.Combine(dir, d + ".bmp")); } } ++pos; } Debug("Wrong:{0}", wrong.Count); Debug("Wrong rate:{0:F2}%", 100.0 * wrong.Count / testcount); }
private void openSC(string dir) { new Thread(new ThreadStart(() => { timer.Restart(); const int shapeme_count = 100; shapemes = new double[shapeme_count][]; showStatus("加载Shapeme"); #region Shapeme using (var fs = new FileStream(Path.Combine(dir, "data.sm"), FileMode.Open)) { using (var br = new BinaryReader(fs)) { for (int i = 0; i < shapeme_count; ++i) { shapemes[i] = new double[60]; for (int k = 0; k < 60; ++k) { shapemes[i][k] = br.ReadDouble(); } showProgress((i + 1.0) / shapeme_count); } } } #endregion #region SCQ showStatus("加载量化形状上下文"); var template_files = Directory.GetFiles(Path.Combine(dir, "scq"), "*.scq").ToArray(); int template_count = template_files.Length; template_histograms = new int[template_count][]; template_chars = new string[template_count]; for (int f = 0; f < template_count; ++f) { string file = template_files[f]; string filename = Path.GetFileNameWithoutExtension(file); template_chars[f] = filename.Split('-')[1]; template_histograms[f] = new int[shapeme_count]; using (var fs = new FileStream(file, FileMode.Open)) { using (var br = new BinaryReader(fs)) { for (int i = 0; i < shapeme_count; ++i) { template_histograms[f][i] = br.ReadInt32(); } } } showProgress((f + 1.0) / template_count); } #endregion #region SC showStatus("加载形状上下文"); var sc_files = Directory.GetFiles(Path.Combine(dir, "sc"), "*.sc").ToArray(); template_sc = new double[template_count][, ]; for (int f = 0; f < template_count; ++f) { string file = sc_files[f]; string filename = Path.GetFileNameWithoutExtension(file); template_sc[f] = new double[100, 60]; using (var fs = new FileStream(file, FileMode.Open)) { using (var br = new BinaryReader(fs)) { for (int j = 0; j < 100; ++j) { for (int k = 0; k < 60; ++k) { template_sc[f][j, k] = br.ReadDouble(); } } } } showProgress((f + 1.0) / template_count); } #endregion showStatus("加载完成,用时{0}ms。", timer.Stop()); })).Start(); }
private static void testCAPTCHA() { var timer = new MyTimer(); int s = 100, K = 100, m = 180; string[] templatefiles = Directory.GetFiles(@"D:\Play Data\my_template_data\scq-" + K + "-" + m, "*.scq") .Take(10000).ToArray(); #region 打开量化的模板 int templatecount = templatefiles.Length; Debug("打开{0}个量化模板----------------------------------------", templatecount); timer.Restart(); int[][] templatehistograms = new int[templatecount][]; string[] templatechars = new string[templatecount]; for (int f = 0; f < templatecount; ++f) { string file = templatefiles[f]; string filename = Path.GetFileNameWithoutExtension(file); templatechars[f] = filename.Split('-')[1]; templatehistograms[f] = new int[K]; using (var fs = new FileStream(file, FileMode.Open)) { using (var br = new BinaryReader(fs)) { for (int i = 0; i < K; ++i) { templatehistograms[f][i] = br.ReadInt32(); } } } } Debug("打开完成,用时{0}ms.", timer.Stop()); #endregion #region 打开Shapeme Debug("打开{0}个Shapeme.", K); timer.Restart(); double[][] shapemes = new double[K][]; using (var fs = new FileStream(Path.Combine(@"D:\Play Data\my_template_data\sm-" + K, m + ".sm"), FileMode.Open)) { using (var br = new BinaryReader(fs)) { for (int i = 0; i < K; ++i) { shapemes[i] = new double[60]; for (int k = 0; k < 60; ++k) { shapemes[i][k] = br.ReadDouble(); } } } } Debug("Shapeme读取完成,用时{0}ms.", timer.Stop()); #endregion #region 识别 foreach (var challengeFile in Directory.GetFiles(@"D:\Play Data\字符\", "*.jpg")) { timer.Restart(); string filename = Path.GetFileNameWithoutExtension(challengeFile); Image<Gray, Byte> img = new Image<Gray, byte>(challengeFile); var mmp = img.Convert<Bgr, Byte>(); Graphics g = Graphics.FromImage(mmp.Bitmap); double width_height_ratio = (double)img.Width / img.Height; int sq = (int)(s * width_height_ratio * 1.2); int randcount = (int)(width_height_ratio * 2); //int windowcount = (int)(width_height_ratio * 2), // windowstep = (int)(img.Width / windowcount), // windowwidth = (int)(img.Width * 1.5 / windowcount); //int maxrandcount = randcount * 3; //Console.WriteLine("宽高比{0:F2},采样{1},随机数{2},随机上限{3}.", // width_height_ratio, sq, randcount, maxrandcount); int slice = 16,//(int)(width_height_ratio * width_height_ratio), overlap = 4, windowcount = 7;//slice - (overlap - 1); double slice_width = (double)img.Width / slice; Console.WriteLine("宽高比{0:F2},切片数{1},切片宽度{2:F2},窗口数{3}.", width_height_ratio, slice, slice_width, windowcount); var edge = getEdge(img).Sample(sq); foreach (var p in edge) { mmp[p] = new Bgr(0, 0, 127); } bool[] edge_vi = Utils.InitArray(sq, false); #region 计算采样点之间的距离 ValueIndexPair<double>[][] edgedists = new ValueIndexPair<double>[sq][]; for (int i = 0; i < sq; ++i) { edgedists[i] = new ValueIndexPair<double>[sq]; for (int j = 0; j < sq; ++j) { double xi = edge[i].X, yi = edge[i].Y, xj = edge[j].X, yj = edge[j].Y; double d = Math.Sqrt((xi - xj) * (xi - xj) + (yi - yj) * (yi - yj)); edgedists[i][j] = new ValueIndexPair<double> { Value = d, Index = j }; } Array.Sort(edgedists[i], (a, b) => a.Value.CompareTo(b.Value)); } #endregion var charlist = new List<Tuple<string, int, PointF>>(); // <ch, count, center> //for (int rc = 0, rt = 0; rc < randcount && rt < maxrandcount; ++rt) { // #region 随机取一个中心点,并且取离他近的点计算形状上下文 //int center = rand.Next(sq); //if (edge_vi[center]) continue; //else rc++; //rc++; //var nearby = new List<Point>(); //foreach (var pair in edgedists[center].Take((int)(s * 1.5))) { // nearby.Add(edge[pair.Index]); // edge_vi[pair.Index] = true; //} //nearby = nearby.Sample(s); for (int wd = 0; wd < windowcount; ++wd) { #region 滑动窗口位置 //int window_center = wd * windowstep + (windowwidth / 2); double window_center = (wd * 2 + overlap / 2.0) * slice_width; g.DrawLine(Pens.Green, (float)window_center, 0, (float)window_center, img.Height); var nearby = edge.Where(p => Math.Abs(p.X - window_center) < img.Height) .OrderBy(p => Math.Abs(p.X - window_center)) .Take((int)(s * 1.2)) .ToList().Sample(s); if (nearby.Average(p => Math.Abs(p.X - window_center)) > img.Height) continue; var sc = Jim.OCR.ShapeContext2D.ShapeContext.ComputeSC2(nearby); #endregion #region 对待测图的形状上下文进行量化 int[] histogram = new int[K]; for (int i = 0; i < s; ++i) { double[] ds = new double[K]; for (int j = 0; j < K; ++j) ds[j] = Jim.OCR.ShapeContext2D.ShapeContext.HistCost(sc[i], shapemes[j]); int id = ds.Select((v, idx) => new ValueIndexPair<double> { Value = v, Index = idx }) .OrderBy(p => p.Value) .First().Index; ++histogram[id]; } #endregion #region 计算量化后的比较距离 double[] dists = new double[templatecount]; for (int i = 0; i < templatecount; ++i) { //dists[i] = Jim.OCR.ShapeContext2D.ShapeContext.ChiSquareDistance(histogram, templatehistograms[i]); dists[i] = Jim.OCR.ShapeContext2D.ShapeContext.HistCost( histogram.Select(d => (double)d).ToArray(), templatehistograms[i].Select(d => (double)d).ToArray()); } #endregion #region 对结果进行排序和统计 var arr = dists.Select((d, i) => new ValueIndexPair<double> { Value = d, Index = i }) .OrderBy(p => p.Value) .Select(p => new { Distance = p.Value, Char = templatechars[p.Index] }) .Where(p => "0123456789".IndexOf(p.Char) != -1) .ToArray(); Dictionary<string, int> matchcount = new Dictionary<string, int>(); int knn = 10; foreach (var pair in arr.Take(knn)) { string ch = pair.Char; matchcount[ch] = matchcount.ContainsKey(ch) ? matchcount[ch] + 1 : 1; } var match = matchcount.Select(pair => new { Count = pair.Value, Ch = pair.Key }) .Where(v => v.Count > 0) .OrderByDescending(v => v.Count).ToArray(); var firstmatch = match[0]; PointF newcenter = new PointF(nearby.Average(p => (float)p.X), nearby.Average(p => (float)p.Y)); charlist.Add(new Tuple<string, int, PointF> { First = firstmatch.Ch, Second = firstmatch.Count, Third = newcenter }); #endregion } foreach (var tp in charlist) { string ch = tp.First; int acc = tp.Second; PointF center = tp.Third; //g.DrawString(num.ToString(), new Font("Arial", 24), new SolidBrush(Color.FromArgb(40 + 20 * acc, 0, 0)), // new PointF(center.X - 12, center.Y - 12)); g.DrawString(ch, new Font("Arial", 24), (acc >= 5 ? Brushes.Red : Brushes.DarkGreen), new PointF(center.X - 12, center.Y - 12)); } mmp.Save(Path.Combine(@"D:\Play Data\测试玩意\", filename + ".jpg")); Debug("{0}-{1}ms", filename, timer.Stop()); } #endregion }
private static void quantizeSC() { MyTimer timer = new MyTimer(); int s = 100, K = 100, m = 180; string[] templatefiles = Directory.GetFiles(@"D:\Play Data\my_template_data\sc\", "*.sc") .Skip(0).Take(1000).ToArray(); int templatecount = templatefiles.Length; #region 打开Shapeme Debug("打开{0}个Shapeme.", K); timer.Restart(); double[][] shapemes = new double[K][]; using (var fs = new FileStream(Path.Combine(@"D:\Play Data\my_template_data\sm-" + K, m + ".sm"), FileMode.Open)) { using (var br = new BinaryReader(fs)) { for (int i = 0; i < K; ++i) { shapemes[i] = new double[60]; for (int k = 0; k < 60; ++k) { shapemes[i][k] = br.ReadDouble(); } } } } Debug("Shapeme读取完成,用时{0}ms.", timer.Stop()); #endregion #region 读取模板和量化 Debug("对{0}个模板进行量化--------------------------------------------", templatecount); timer.Restart(); for (int f = 0; f < templatecount; ++f) { string file = templatefiles[f]; string filename = Path.GetFileNameWithoutExtension(file); int[] histogram = new int[K]; using (var fs = new FileStream(file, FileMode.Open)) { using (var br = new BinaryReader(fs)) { for (int j = 0; j < s; ++j) { double[] sc = new double[60]; for (int k = 0; k < 60; ++k) { sc[k] = br.ReadDouble(); } double[] dists = new double[K]; for (int k = 0; k < K; ++k) dists[k] = Jim.OCR.ShapeContext2D.ShapeContext.HistCost(sc, shapemes[k]); int id = dists.Select((v, idx) => new ValueIndexPair<double> { Value = v, Index = idx }) .OrderBy(p => p.Value) .First().Index; ++histogram[id]; } } } using (var fs = new FileStream(Path.Combine(@"D:\Play Data\my_template_data\scq-" + K + "-" + m, filename + ".scq"), FileMode.Create)) { using (var bw = new BinaryWriter(fs)) { for (int i = 0; i < K; ++i) { bw.Write(histogram[i]); } } } if (f % 100 == 0) Debug("已完成{0}个", f); } Debug("量化完成,用时{0}ms.", timer.Stop()); #endregion }
private static void MatchShapeContext(string path, string fa, string fb, char c) { MyTimer timer = new MyTimer(); Console.WriteLine("Doing...{0}", c); var sca = CreateShapeContext(path, fa, 100, c); var scb = CreateShapeContext(path, fb, 100, c); var match = new ShapeContextMatching(sca.ShapeContests, scb.ShapeContests); timer.Restart(); match.BuildCostGraph(); timer.StopAndSay("Build Graph"); timer.Restart(); var km = match.Match(); timer.StopAndSay("Match"); Console.WriteLine("Match Result:{0}", km.MatchResult); int ax = (int)sca.Points.Average(p => p.X), ay = (int)sca.Points.Average(p => p.Y), bx = (int)scb.Points.Average(p => p.X), by = (int)scb.Points.Average(p => p.Y); int dx = bx - ax, dy = by - ay; int scale = 4; Image<Bgr, Byte> img = new Image<Bgr, byte>(400 * scale, 400 * scale); string scdir = Path.Combine(path, c.ToString()); if (Directory.Exists(scdir)) Directory.Delete(scdir, true); Directory.CreateDirectory(scdir); Font fs = new Font("Arial", 12); using (Graphics g = Graphics.FromImage(img.Bitmap)) { g.Clear(Color.Black); Font font1 = new Font(fa, 240 * scale); Font font2 = new Font(fb, 240 * scale); g.DrawString(c.ToString(), font1, new SolidBrush(Color.FromArgb(30, 255, 0, 0)), new Point(0, 0)); g.DrawString(c.ToString(), font2, new SolidBrush(Color.FromArgb(30, 0, 255, 0)), new Point(-dx * scale, -dy * scale)); for (int j = 0; j < scb.Points.Count; ++j) { int i = km.MatchPair[j + sca.Points.Count]; Point pb = scb.Points[j], pa = sca.Points[i]; pb.X -= dx; pb.Y -= dy; int r = 3; g.DrawEllipse(Pens.Red, pa.X * scale - r, pa.Y * scale - r, r * 2 + 1, r * 2 + 1); g.DrawEllipse(Pens.Green, pb.X * scale - r, pb.Y * scale - r, r * 2 + 1, r * 2 + 1); g.DrawLine(Pens.Gray, new Point(pa.X * scale, pa.Y * scale), new Point(pb.X * scale, pb.Y * scale)); Point ps = new Point(pa.X * scale, pa.Y * scale); g.DrawString(i.ToString(), fs, Brushes.White, ps); string hisa = Path.Combine(scdir, String.Format("{0}-{1}.bmp", i, fa)); string hisb = Path.Combine(scdir, String.Format("{0}-{1}.bmp", i, fb)); sca.ShapeContests[i].Histogram.ToImage().Save(hisa); scb.ShapeContests[j].Histogram.ToImage().Save(hisb); } } img.Save(Path.Combine(path, String.Format("{0}-{1}-{2}.bmp", fa, fb, c))); }
private Image<Bgr, Byte> kmeans() { int trainSampleCount = 1500; int sigma = 60; Matrix<float> trainData = new Matrix<float>(trainSampleCount, 2); Matrix<float> trainData1 = trainData.GetRows(0, trainSampleCount / 3, 1); trainData1.GetCols(0, 1).SetRandNormal(new MCvScalar(100), new MCvScalar(sigma)); trainData1.GetCols(1, 2).SetRandNormal(new MCvScalar(300), new MCvScalar(sigma)); Matrix<float> trainData2 = trainData.GetRows(trainSampleCount / 3, 2 * trainSampleCount / 3, 1); trainData2.SetRandNormal(new MCvScalar(400), new MCvScalar(sigma)); Matrix<float> trainData3 = trainData.GetRows(2 * trainSampleCount / 3, trainSampleCount, 1); trainData3.GetCols(0, 1).SetRandNormal(new MCvScalar(300), new MCvScalar(sigma)); trainData3.GetCols(1, 2).SetRandNormal(new MCvScalar(100), new MCvScalar(sigma)); PointF[] points = new PointF[trainSampleCount]; for (int i = 0; i < points.Length; ++i) { points[i] = new PointF(trainData[i, 0], trainData[i, 1]); } var km = new KMeans<PointF>(points, 3, (a, b) => ((a.X - b.X) * (a.X - b.X) + (a.Y - b.Y) * (a.Y - b.Y)), list => new PointF(list.Average(p => p.X), list.Average(p => p.Y)) ); int it = 0; MyTimer timer = new MyTimer(); timer.Restart(); //var cluster = km.Cluster(); var cluster = km.AnnealCluster( (a, b) => new PointF(a.X + b.X, a.Y + b.Y), (a, b) => new PointF(a.X - b.X, a.Y - b.Y), (p, v) => new PointF((float)(p.X / v), (float)(p.Y / v)), out it); var time = timer.Stop(); this.Text = String.Format("n={0}, k={1}, time={2}ms, iter={3}.", trainSampleCount, 3, time, it); Image<Bgr, Byte> img = new Image<Bgr, byte>(500, 500); for (int y = 0; y < 500; ++y) { for (int x = 0; x < 500; ++x) { double d0 = (x - cluster[0].Center.X) * (x - cluster[0].Center.X) + (y - cluster[0].Center.Y) * (y - cluster[0].Center.Y); double d1 = (x - cluster[1].Center.X) * (x - cluster[1].Center.X) + (y - cluster[1].Center.Y) * (y - cluster[1].Center.Y); double d2 = (x - cluster[2].Center.X) * (x - cluster[2].Center.X) + (y - cluster[2].Center.Y) * (y - cluster[2].Center.Y); Bgr color = new Bgr(0, 0, 0); if (d0 < d1 && d0 < d2) { color = new Bgr(20, 0, 0); } if (d1 < d0 && d1 < d2) { color = new Bgr(0, 20, 0); } if (d2 < d0 && d2 < d1) { color = new Bgr(0, 0, 20); } img[y, x] = color; } } Bgr[] colors = new[] { new Bgr(128, 0, 0), new Bgr(0, 128, 0), new Bgr(0, 0, 128) }; Bgr[] centers = new[] { new Bgr(255, 0, 0), new Bgr(0, 255, 0), new Bgr(0, 0, 255) }; for (int i = 0; i < 3; ++i) { foreach (var p in cluster[i]) { img.Draw(new CircleF(p, 2), colors[i], 1); } img.Draw(new CircleF(cluster[i].Center, 5), centers[i], 3); } img.Draw(new CircleF(new PointF(100, 300), sigma), new Bgr(128, 128, 128), 2); img.Draw(new CircleF(new PointF(100, 300), 3), new Bgr(128, 128, 128), 2); img.Draw(new CircleF(new PointF(300, 100), sigma), new Bgr(128, 128, 128), 2); img.Draw(new CircleF(new PointF(300, 100), 3), new Bgr(128, 128, 128), 2); img.Draw(new CircleF(new PointF(400, 400), sigma), new Bgr(128, 128, 128), 2); img.Draw(new CircleF(new PointF(400, 400), 3), new Bgr(128, 128, 128), 2); return img; }
private void gao() { clearText(); string filename = label1.Text; string path = Path.GetDirectoryName(filename); string file = Path.GetFileNameWithoutExtension(filename); string savepath = Path.Combine(path, "out"); appendLine(filename); Image <Bgr, Byte> bmp = new Image <Bgr, byte>(filename); Image <Gray, Byte> gray = bmp.Convert <Gray, Byte>(); double threshold = new MaxVarianceBinarization().CalculateThreshold(gray); appendLine("阈值:{0}", threshold); //Image<Gray, Byte> bi = gray.ThresholdBinaryInv(new Gray(threshold), new Gray(255)); // Image<Gray, Byte> dn = bi.SmoothMedian(3); int it; //Stopwatch timer = Stopwatch.StartNew(); //Image<Gray, Byte> dn = new AnnealKMeansClusterDenoise().Denoise(bi, 1, out it); //timer.Stop(); //appendLine("降噪用时{0}ms,迭代次数{1}。", timer.ElapsedMilliseconds, it); //var con = dn.FindContours(); //bmp.Draw(con, new Bgr(0, 0, 255), new Bgr(255, 0, 0), 1, 1); //var proj = Projecting.VerticalProject(dn); //var proj = bi.SmoothMedian(3); //var proj = dn - dn.Erode(1);//dn.Dilate(1) - bi; //var proj = gray.MorphologyEx(see, Emgu.CV.CvEnum.CV_MORPH_OP.CV_MOP_OPEN, 1); //var proj = //showImage(imageBox1, bi); //showImage(imageBox2, dn); //showImage(imageBox1, gray); //showImage(imageBox1, gray); timer.Restart(); var mask = gray.SmoothMask(); showImage(imageBox1, mask); appendLine("掩模:{0}ms", timer.Stop()); timer.Restart(); double thr = new MaxVarianceBinarization().CalculateThreshold(mask); var thrd = mask.ThresholdBinaryInv(new Gray(thr), new Gray(255)); showImage(imageBox2, thrd); appendLine("二值:{0}ms", timer.Stop()); timer.Restart(); var smooth = thrd.SmoothMedian(7); showImage(imageBox3, smooth); appendLine("中值滤波:{0}ms", timer.Stop()); timer.Restart(); var dm = new AnnealKMeansClusterDenoise().Denoise(thrd, 0, out it).SmoothMedian(5); showImage(imageBox4, dm); appendLine("区域联通:{0}ms", timer.Stop()); #region 灰度分级连通 //int level = 16; //var gray4 = mask.ToGrayN(level); //showImage(imageBox1, gray4); //timer.Restart(); //var conns = gray4.Connect(level); //appendLine("分级:{0}ms", timer.Stop()); //var mins = Utils.FindLocalMins(conns.Select(c => c.Domains.Count).ToArray()); //var list = new List<ConnectLevel>(); //for (int i = 1; i < mins.Length; ++i) { // var cl = conns[mins[i]]; // if (cl.Domains.Count == 1) continue; // if (cl.MeanArea < 10) continue; // if (cl.Variance > 20000) continue; // //if (mins[i] - mins[i - 1] == 1) { // // var lastcl = conns[mins[i] - 1]; // // if (lastcl.Domains.Count != cl.Domains.Count) // // list.Add(cl); // //} else { // // list.Add(cl); // //} // list.Add(cl); //} //list.ForEach( // c => appendLine("Lv{0},C{1},MA{2:F2},VA{3:F4}", c.Level, c.Domains.Count, c.MeanArea, c.Variance)); //timer.Restart(); //var bestlevel = list.OrderByDescending(c => c.MeanArea).ThenBy(c => c.Domains.Count).First(); //var colored = gray4.ColorLevel(bestlevel); //var see = new StructuringElementEx(4, 4, 1, 1, Emgu.CV.CvEnum.CV_ELEMENT_SHAPE.CV_SHAPE_ELLIPSE); //var bg = colored.Erode(10).Dilate(10); //showImage(imageBox2, colored - bg); //appendLine("染色处理{0}ms", timer.Stop()); #endregion //double t2=new MaxVarianceBinarization().CalculateThreshold(mask); //var proj = mask.ThresholdBinaryInv(new Gray(t2), new Gray(255)); //var akmcd = new AnnealKMeansClusterDenoise(); //var t3 = new MaxVarianceBinarization().CalculateThreshold(mask); //var bi2 = mask.ThresholdBinaryInv(new Gray(t3), new Gray(255)); //showImage(imageBox2, bi2); //var dn2 = akmcd.Denoise(bi2, 1, out it); //showImage(imageBox3, dn2); //var contour = ContourFinder.ColorContours(dn2, new Gray(0), new Gray(255)); //showImage(imageBox5, contour); //var con = dn2.FindContours(); //var con2 = dn2.Convert<Bgr, Byte>(); //con2.Draw(con, new Bgr(0, 0, 255), new Bgr(0, 255, 0), 1, 1); //showImage(imageBox6, con2); //p1 = akmcd.Denoise(p1, 0, out it); //p2 = akmcd.Denoise(p2, 0, out it); //var p3 = p1.Xor(p2); //var p4 = p1 - p3; //var p5 = p2 - p3; //var p6 = p1 - p2; //var p4 = akmcd.Denoise(p1, 0, out it); //var p5 = akmcd.Denoise(p2, 0, out it); //var p6 = akmcd.Denoise(p3, 0, out it); //StructuringElementEx se = new StructuringElementEx(3, 3, 1, 1, Emgu.CV.CvEnum.CV_ELEMENT_SHAPE.CV_SHAPE_RECT); //dn = dn.MorphologyEx(se, Emgu.CV.CvEnum.CV_MORPH_OP.CV_MOP_OPEN, 1); //var canny = dn.Canny(new Gray(threshold), new Gray(threshold * 0.6)); //showImage(imageBox1, bmp); //showImage(imageBox2, gray); //showImage(imageBox3, bi); //showImage(imageBox4, dn); //showImage(imageBox5, p1); //showImage(imageBox6, p2); //showImage(imageBox4, p4); //showImage(imageBox5, p5); //showImage(imageBox6, p6); }
private static void fastPruningWithShapeme() { var timer = new MyTimer(); int s = 100, K = 100, m = 100; string[] templatefiles = Directory.GetFiles(@"D:\Play Data\train_data\scq-" + K + "-" + m, "*.scq") .Take(20000).ToArray(); #region 打开量化的模板 int templatecount = templatefiles.Length; Debug("打开{0}个量化模板----------------------------------------", templatecount); timer.Restart(); int[][] templatehistograms = new int[templatecount][]; int[] templatenums = new int[templatecount]; for (int f = 0; f < templatecount; ++f) { string file = templatefiles[f]; string filename = Path.GetFileNameWithoutExtension(file); templatenums[f] = int.Parse(filename.Split('-')[1]); templatehistograms[f] = new int[K]; using (var fs = new FileStream(file, FileMode.Open)) { using (var br = new BinaryReader(fs)) { for (int i = 0; i < K; ++i) { templatehistograms[f][i] = br.ReadInt32(); } } } } Debug("打开完成,用时{0}ms.", timer.Stop()); #endregion #region 打开Shapeme Debug("打开{0}个Shapeme.", K); timer.Restart(); double[][] shapemes = new double[K][]; using (var fs = new FileStream(Path.Combine(@"D:\Play Data\train_data\sm-" + K, m + ".sm"), FileMode.Open)) { using (var br = new BinaryReader(fs)) { for (int i = 0; i < K; ++i) { shapemes[i] = new double[60]; for (int k = 0; k < 60; ++k) { shapemes[i][k] = br.ReadDouble(); } } } } Debug("Shapeme读取完成,用时{0}ms.", timer.Stop()); #endregion string[] testfiles = Directory.GetFiles(@"D:\Play Data\test\", "*.bmp") .Take(1000).ToArray(); #region 测试 int testcase = testfiles.Length, acc = 0; Debug("为{0}个对象寻找候选模板------------------------------------------", testcase); foreach (var file in testfiles) { timer.Restart(); #region 计算待测图的形状上下文 string filenameext = Path.GetFileName(file); string filename = Path.GetFileNameWithoutExtension(file); int thisnum = int.Parse(filename.Split('-')[1]); Image<Gray, Byte> img = new Image<Gray, byte>(file); var list = getEdge(img.Resize(2.5, Emgu.CV.CvEnum.INTER.CV_INTER_LINEAR)).Sample(s); var sc = Jim.OCR.ShapeContext2D.ShapeContext.ComputeSC2(list); #endregion #region 对待测图的形状上下文进行量化 int[] histogram = new int[K]; for (int i = 0; i < s; ++i) { double[] ds = new double[K]; for (int j = 0; j < K; ++j) ds[j] = Jim.OCR.ShapeContext2D.ShapeContext.HistCost(sc[i], shapemes[j]); int id = ds.Select((v, idx) => new ValueIndexPair<double> { Value = v, Index = idx }) .OrderBy(p => p.Value) .First().Index; ++histogram[id]; } #endregion #region 计算量化后的比较距离 double[] dists = new double[templatecount]; for (int i = 0; i < templatecount; ++i) { dists[i] = Jim.OCR.ShapeContext2D.ShapeContext.ChiSquareDistance(histogram, templatehistograms[i]); //dists[i] = Jim.OCR.ShapeContext2D.ShapeContext.HistCost(histogram.Cast<double>().ToArray(), templatehistograms[i].Cast<double>().ToArray()); } #endregion #region 对结果进行排序和统计 var arr = dists.Select((d, i) => new ValueIndexPair<double> { Value = d, Index = i }) .OrderBy(p => p.Value) .Select(p => new { Distance = p.Value, Num = templatenums[p.Index] }) .ToArray(); int[] matchcount = new int[10]; int knn = 10; foreach (var pair in arr.Take(knn)) { int num = pair.Num; matchcount[num]++; } var match = matchcount.Select((val, i) => new { Count = val, Num = i }) .Where(v => v.Count > 0) .OrderByDescending(v => v.Count).ToArray(); #endregion int firstmatch = match[0].Num; var fc = Console.ForegroundColor; Console.ForegroundColor = firstmatch == thisnum ? ConsoleColor.Green : ConsoleColor.Red; string info = String.Format("{0} {1}ms - {2}\t", filename, timer.Stop(), (firstmatch == thisnum ? "Right" : "Wrong")); foreach (var ma in match.Take(4)) { info += String.Format("{0}/{1}\t", ma.Num, ma.Count); } Debug(info); Console.ForegroundColor = fc; if (firstmatch == thisnum) { ++acc; } } Debug("测试用例:{0}。正确率{1}。", testcase, acc); #endregion }
private Image <Bgr, Byte> kmeans() { int trainSampleCount = 1500; int sigma = 60; Matrix <float> trainData = new Matrix <float>(trainSampleCount, 2); Matrix <float> trainData1 = trainData.GetRows(0, trainSampleCount / 3, 1); trainData1.GetCols(0, 1).SetRandNormal(new MCvScalar(100), new MCvScalar(sigma)); trainData1.GetCols(1, 2).SetRandNormal(new MCvScalar(300), new MCvScalar(sigma)); Matrix <float> trainData2 = trainData.GetRows(trainSampleCount / 3, 2 * trainSampleCount / 3, 1); trainData2.SetRandNormal(new MCvScalar(400), new MCvScalar(sigma)); Matrix <float> trainData3 = trainData.GetRows(2 * trainSampleCount / 3, trainSampleCount, 1); trainData3.GetCols(0, 1).SetRandNormal(new MCvScalar(300), new MCvScalar(sigma)); trainData3.GetCols(1, 2).SetRandNormal(new MCvScalar(100), new MCvScalar(sigma)); PointF[] points = new PointF[trainSampleCount]; for (int i = 0; i < points.Length; ++i) { points[i] = new PointF(trainData[i, 0], trainData[i, 1]); } var km = new KMeans <PointF>(points, 3, (a, b) => ((a.X - b.X) * (a.X - b.X) + (a.Y - b.Y) * (a.Y - b.Y)), list => new PointF(list.Average(p => p.X), list.Average(p => p.Y)) ); int it = 0; MyTimer timer = new MyTimer(); timer.Restart(); //var cluster = km.Cluster(); var cluster = km.AnnealCluster( (a, b) => new PointF(a.X + b.X, a.Y + b.Y), (a, b) => new PointF(a.X - b.X, a.Y - b.Y), (p, v) => new PointF((float)(p.X / v), (float)(p.Y / v)), out it); var time = timer.Stop(); this.Text = String.Format("n={0}, k={1}, time={2}ms, iter={3}.", trainSampleCount, 3, time, it); Image <Bgr, Byte> img = new Image <Bgr, byte>(500, 500); for (int y = 0; y < 500; ++y) { for (int x = 0; x < 500; ++x) { double d0 = (x - cluster[0].Center.X) * (x - cluster[0].Center.X) + (y - cluster[0].Center.Y) * (y - cluster[0].Center.Y); double d1 = (x - cluster[1].Center.X) * (x - cluster[1].Center.X) + (y - cluster[1].Center.Y) * (y - cluster[1].Center.Y); double d2 = (x - cluster[2].Center.X) * (x - cluster[2].Center.X) + (y - cluster[2].Center.Y) * (y - cluster[2].Center.Y); Bgr color = new Bgr(0, 0, 0); if (d0 < d1 && d0 < d2) { color = new Bgr(20, 0, 0); } if (d1 < d0 && d1 < d2) { color = new Bgr(0, 20, 0); } if (d2 < d0 && d2 < d1) { color = new Bgr(0, 0, 20); } img[y, x] = color; } } Bgr[] colors = new[] { new Bgr(128, 0, 0), new Bgr(0, 128, 0), new Bgr(0, 0, 128) }; Bgr[] centers = new[] { new Bgr(255, 0, 0), new Bgr(0, 255, 0), new Bgr(0, 0, 255) }; for (int i = 0; i < 3; ++i) { foreach (var p in cluster[i]) { img.Draw(new CircleF(p, 2), colors[i], 1); } img.Draw(new CircleF(cluster[i].Center, 5), centers[i], 3); } img.Draw(new CircleF(new PointF(100, 300), sigma), new Bgr(128, 128, 128), 2); img.Draw(new CircleF(new PointF(100, 300), 3), new Bgr(128, 128, 128), 2); img.Draw(new CircleF(new PointF(300, 100), sigma), new Bgr(128, 128, 128), 2); img.Draw(new CircleF(new PointF(300, 100), 3), new Bgr(128, 128, 128), 2); img.Draw(new CircleF(new PointF(400, 400), sigma), new Bgr(128, 128, 128), 2); img.Draw(new CircleF(new PointF(400, 400), 3), new Bgr(128, 128, 128), 2); return(img); }
private static void testCluter() { int ss = 100, sq = 100, k = 10, m = 10; // 采样数,G取前k,S取前m int randcount = 5, randtake = 10, randselect = 3; var timer = new MyTimer(); var templatefiles = Directory.GetFiles(@"D:\Play Data\字符模板"); int templatecount = templatefiles.Length; var templateChars = new string[templatecount]; var templatePoints = new Vector2[templatecount][]; //var templatesc = new double[templatecount][,]; var templatesc = new double[templatecount][][]; #region 计算模板的SC for (int f = 0; f < templatecount; ++f) { string file = templatefiles[f], filename = Path.GetFileNameWithoutExtension(file); using (Image<Gray, Byte> img = new Image<Gray, byte>(file)) { var samples = getEdge(img).Sample(ss); templatesc[f] = Jim.OCR.ShapeContext2D.ShapeContext.ComputeSC2(samples); templatePoints[f] = samples.Select(p => new Vector2(p.X, p.Y)).ToArray(); } templateChars[f] = filename; Console.Write(filename); } Console.WriteLine(); Debug("模板读取完成"); #endregion #region 处理字符 foreach (string file in Directory.GetFiles(@"D:\Play Data\字符")) { string filename = Path.GetFileNameWithoutExtension(file); if (filename != "AB") continue; timer.Restart(); Image<Bgr, Byte> img = new Image<Bgr, Byte>(file); var samples = getEdge(img.Convert<Gray, Byte>()).Sample(sq); //double[,] SCQ = Jim.OCR.ShapeContext2D.ShapeContext.ComputeSC(samples); double[][] SCQ = Jim.OCR.ShapeContext2D.ShapeContext.ComputeSC2(samples); var Q_Points = samples.Select(p => new Vector2(p.X, p.Y)).ToArray(); var mmg = img.Convert<Bgr, Byte>(); Graphics g = Graphics.FromImage(mmg.Bitmap); Q_Points.ToList().ForEach(v => { mmg[(int)v.Y, (int)v.X] = new Bgr(0, 0, 255); }); var point_distance = new ValueIndexPair<double>[sq][]; #region 计算采样点之间的距离 for (int i = 0; i < sq; ++i) { double xi = Q_Points[i].X, yi = Q_Points[i].Y; point_distance[i] = new ValueIndexPair<double>[sq]; for (int j = 0; j < sq; ++j) { double xj = Q_Points[j].X, yj = Q_Points[j].Y; point_distance[i][j] = new ValueIndexPair<double> { Value = Math.Sqrt((xi - xj) * (xi - xj) + (yi - yj) * (yi - yj)), Index = j }; } Array.Sort(point_distance[i], (a, b) => a.Value.CompareTo(b.Value)); } #endregion var randpoints = new int[randcount][]; #region 随机取randcount个点,并在其周围randtake个点中取randselect个 for (int i = 0; i < randcount; ++i) { int pi = rand.Next(Q_Points.Length); var p = Q_Points[pi]; mmg.Draw(new CircleF(new PointF((float)p.X, (float)p.Y), 2), new Bgr(255, 0, 0), 1); randpoints[i] = new int[randselect]; bool[] vi = Utils.InitArray<bool>(randtake, false); for (int cnt = 0; cnt < randselect; ) { int rnd = rand.Next(randtake); if (!vi[rnd]) { vi[rnd] = true; randpoints[i][cnt++] = rnd; } } for (int ppp = 0; ppp < randselect; ++ppp) { var pt = Q_Points[point_distance[pi][randpoints[i][ppp]].Index]; //g.DrawString(i.ToString(), new Font("Arial", 7), new SolidBrush(Color.FromArgb(0, 128, 0)), new PointF((float)pt.X, (float)pt.Y)); } } #endregion #region 为这randcount组RSC分别选最好的模板 var rscmatch = new Tuple<int, double, Vector2>[randcount]; // <Si, d, L> for (int rc = 0; rc < randcount; ++rc) { var rsc_matches = new Tuple<double, Vector2>[templatecount]; // <d, L> for (int i = 0; i < templatecount; ++i) { #region 拷贝出一个rsc来 var rsc = new double[randselect][]; for (int j = 0; j < randselect; ++j) { rsc[j] = new double[60]; Array.Copy(SCQ[randpoints[rc][j]], rsc[j], 60); } #endregion var costmat = Jim.OCR.ShapeContext2D.ShapeContext.HistCost2(rsc, templatesc[i]); var matches = costmat.Select( row => row.Select((d, c) => new ValueIndexPair<double> { Value = d, Index = c }) .OrderBy(d => d.Value).First()).ToArray(); Vector2 L = Vector2.Zero; double M = 0; for (int j = 0; j < randselect; ++j) { int u = randpoints[rc][j], mu = matches[j].Index; double d = matches[j].Value; Vector2 pu = Q_Points[u], pmu = templatePoints[i][mu]; M += (1 - d); L += (1 - d) * (pu - pmu); } L /= M; rsc_matches[i] = new Tuple<double, Vector2> { First = matches.Sum(r => r.Value), Second = L }; } var best_template = rsc_matches.Select((mt, i) => new { Match = mt, i }) .OrderBy(t => t.Match.First) .First(); rscmatch[rc] = new Tuple<int, double, Vector2> { First = best_template.i, Second = best_template.Match.First, Third = best_template.Match.Second }; string label = templateChars[best_template.i]; g.DrawString(label, new Font("Arial", 48), Brushes.Green, new PointF((float)best_template.Match.Second.X, (float)best_template.Match.Second.Y)); } #endregion //Font f = new Font("Arial", 12); //var G = new Tuple<int, int, double>[templatecount][]; // <u, m(u), d> //#region 为每个Si挑选合适的Gi //{ // var costmats = new double[templatecount][,]; // for (int i = 0; i < templatecount; ++i) { // double[,] SCi = templatesc[i]; // costmats[i] = Jim.OCR.ShapeContext2D.ShapeContext.HistCost(SCQ, SCi); // G[i] = new Tuple<int, int, double>[sq * ss]; // for (int u = 0; u < sq; ++u) { // for (int j = 0; j < ss; ++j) { // G[i][u * ss + j] = new Tuple<int, int, double> { // First = u, // Second = j, // Third = costmats[i][u, j] // }; // } // } // Array.Sort(G[i], (da, db) => da.Third.CompareTo(db.Third)); // } //} //#endregion //var d_Q_S = new double[templatecount]; //#region 求出每个Si和Q的d(Q, Si) //{ // for (int i = 0; i < templatecount; ++i) { // var Gi = G[i].Take(k); // foreach (var g in Gi) { // int u = g.First, mu = g.Second; // double d = g.Third; // double Nu = G.Average(gi => gi.First(t => t.First == u).Third); // d_Q_S[i] += d / Nu; // } // d_Q_S[i] /= k; // } //} //#endregion //var firstmG = new Tuple<Tuple<int, int, double>[], double, int>[m]; // <G, d, i> <=> <<u, m(u), d>[], d, i> //#region 根据d(Q, Si)截取前20个最好的Gi //{ // var firstmdQS = d_Q_S.Select((d, i) => new ValueIndexPair<double> { Value = d, Index = i }) // .OrderBy(p => p.Value) // .Take(firstmG.Length).ToArray(); // for (int p = 0; p < firstmG.Length; ++p) { // double d = firstmdQS[p].Value; // int i = firstmdQS[p].Index; // firstmG[p] = new Tuple<Tuple<int, int, double>[], double, int> { // First = G[i].Take(k).ToArray(), // Second = d, // Third = i // }; // } //} //#endregion //#region 计算每个G的位置 //var L = new Vector2[m]; //{ // for (int i = 0; i < m; ++i) { // L[i] = Vector2.Zero; // double Mi = 0; // var Gi = firstmG[i]; // foreach (var u_mu_d in Gi.First) { // int u = u_mu_d.First, mu = u_mu_d.Second; // double d = u_mu_d.Third; // Vector2 pu = Q_Points[u], pmu = templatePoints[Gi.Third][mu]; // L[i] += (1 - d) * (pu - pmu); // Mi += (1 - d); // } // L[i] /= Mi; // g.DrawString(templateChars[Gi.Third], new Font("Arial", 12), Brushes.Green, // new PointF((float)L[i].X, (float)L[i].Y)); // } //} //#endregion mmg.Save(Path.Combine(@"D:\Play Data\测试玩意", filename + ".bmp")); Debug("{0}\t用时{1}ms.", filename, timer.Stop()); } #endregion }