Beispiel #1
0
        public Tuple<string, int> Recognize(Image<Gray, byte> src)
        {
            var list = src.getEdge().Sample(100);

            #region 计算形状上下文
            int r = 15;
            var scall = Jim.OCR.ShapeContext2D.ShapeContext.ComputeSC(list);
            var scq = new double[r, 60];
            for (int i = 0; i < r; ++i) {
                int pos = rand.Next(list.Count);
                for (int k = 0; k < 60; ++k) {
                    scq[i, k] = scall[pos, k];
                }
            }
            #endregion
            #region 计算距离
            var dists = new ValueIndexPair<double>[SC.template_sc.Length];
            for (int i = 0; i < SC.template_sc.Length; ++i) {
                double[,] sci = SC.template_sc[i];
                double[,] costmat = Jim.OCR.ShapeContext2D.ShapeContext.HistCost(scq, sci);
                double cost = 0;
                for (int j = 0; j < r; ++j) {
                    double min = double.MaxValue;
                    for (int u = 0; u < 100; ++u) {
                        double val = costmat[j, u];
                        if (val < min) min = val;
                    }
                    cost += min;
                }
                dists[i] = new ValueIndexPair<double> { Value = cost, Index = i };
            }
            #endregion

            #region 对结果排序
            var arr = dists
                .OrderBy(p => p.Value)
                .Select(p => new { Distance = p.Value, Char = SC.template_chars[p.Index] })
                //.Where(p => "ABCDEFGHIJKLMNPQRSTUVWXYZ123456789".IndexOf(p.Char) != -1)
                .Where(p => Filter.IndexOf(p.Char) != -1)
                .ToArray();
            Dictionary<string, int> matchcount = new Dictionary<string, int>();
            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();
            //string result = "";
            //foreach (var m in match.Take(3)) {
            //    result += String.Format("Char:'{0}',Accuracy:{1}/{2}\t", m.Ch, m.Count, knn);
            //}
            #endregion

            return new Tuple<string, int> { First = match[0].Ch, Second = match[0].Count };
        }
        private void PrepareCalculate()
        {
            check = false;
            int[] arrayInt;
            int   count = Convert.ToInt32(CountFindNumberTextBox.Text);

            UseArray.Clear();
            CalculateArray.Text = "";
            if (EnterArrayTextBox.Text.Length != 0)
            {
                arrayInt = EnterArrayTextBox.Text.Split(' ').Take(Convert.ToInt32(SizeArrayTextBox.Text)).Select(x => int.Parse(x)).ToArray();
                try
                {
                    SortedSet <ValueIndexPair> sorted = new SortedSet <ValueIndexPair>(new ValueIndexCompare());
                    for (int i = 0; i < arrayInt.Length; i++)
                    {
                        var pair = new ValueIndexPair(arrayInt[i], i);
                        if (sorted.Count < count)
                        {
                            sorted.Add(pair);
                        }
                        else
                        {
                            if (sorted.Max.Value < arrayInt[i])
                            {
                                sorted.Remove(sorted.Max);
                                sorted.Add(pair);
                            }
                        }
                    }
                    foreach (var item in sorted)
                    {
                        CalculateArray.Text = CalculateArray.Text + " " + item.Value;
                    }
                    ;
                }
                catch (Exception eEnterArrayTextBox)
                {
                    MessageBoxResult message = MessageBox.Show(eEnterArrayTextBox.Message, "Error", MessageBoxButton.OK);
                    if (message == MessageBoxResult.OK)
                    {
                        check = true;
                    }
                }
            }
        }
Beispiel #3
0
        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
        }
Beispiel #4
0
        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
        }
Beispiel #5
0
        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
        }
Beispiel #6
0
        public Tuple <string, int> Recognize(Image <Gray, byte> src)
        {
            var list = src.getEdge().Sample(100);

            #region 计算形状上下文
            int r     = 15;
            var scall = Jim.OCR.ShapeContext2D.ShapeContext.ComputeSC(list);
            var scq   = new double[r, 60];
            for (int i = 0; i < r; ++i)
            {
                int pos = rand.Next(list.Count);
                for (int k = 0; k < 60; ++k)
                {
                    scq[i, k] = scall[pos, k];
                }
            }
            #endregion
            #region 计算距离
            var dists = new ValueIndexPair <double> [SC.template_sc.Length];
            for (int i = 0; i < SC.template_sc.Length; ++i)
            {
                double[,] sci     = SC.template_sc[i];
                double[,] costmat = Jim.OCR.ShapeContext2D.ShapeContext.HistCost(scq, sci);
                double cost = 0;
                for (int j = 0; j < r; ++j)
                {
                    double min = double.MaxValue;
                    for (int u = 0; u < 100; ++u)
                    {
                        double val = costmat[j, u];
                        if (val < min)
                        {
                            min = val;
                        }
                    }
                    cost += min;
                }
                dists[i] = new ValueIndexPair <double> {
                    Value = cost, Index = i
                };
            }
            #endregion

            #region 对结果排序
            var arr = dists
                      .OrderBy(p => p.Value)
                      .Select(p => new { Distance = p.Value, Char = SC.template_chars[p.Index] })
                      //.Where(p => "ABCDEFGHIJKLMNPQRSTUVWXYZ123456789".IndexOf(p.Char) != -1)
                      .Where(p => Filter.IndexOf(p.Char) != -1)
                      .ToArray();
            Dictionary <string, int> matchcount = new Dictionary <string, int>();
            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();
            //string result = "";
            //foreach (var m in match.Take(3)) {
            //    result += String.Format("Char:'{0}',Accuracy:{1}/{2}\t", m.Ch, m.Count, knn);
            //}
            #endregion

            return(new Tuple <string, int> {
                First = match[0].Ch, Second = match[0].Count
            });
        }
Beispiel #7
0
        public void Run()
        {
            double totaltime = 0;

            int s = 100, r = 5;

            string[] templatefiles = Directory.GetFiles(@"D:\Play Data\train_data\sc\", "*.sc")
                                     .Take(100).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];
                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(1000).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 knn = 10;

                #region 进行精细匹配
                var kmresults = new List <ValueIndexPair <double> >();
                foreach (var pair in arr.Take(knn))
                {
                    int idx     = pair.Index;
                    var costmat = Jim.OCR.ShapeContext2D.ShapeContext.HistCost(templates[idx], sc100);

                    var costmat_int = new int[s, s];
                    for (int ii = 0; ii < s; ++ii)
                    {
                        for (int jj = 0; jj < s; ++jj)
                        {
                            costmat_int[ii, jj] = (int)(costmat[ii, jj] * 10000);
                        }
                    }
                    var km = new KM(s, costmat_int);
                    km.Match(false);

                    kmresults.Add(new ValueIndexPair <double> {
                        Index = idx, Value = km.MatchResult / 10000.0
                    });
                }
                kmresults.Sort((a, b) => a.Value.CompareTo(b.Value));
                #endregion

                //int firstmatch = match[0].Num;
                int firstmatch = templatenums[kmresults[0].Index];
                var fc         = Console.ForegroundColor;
                Console.ForegroundColor = firstmatch == thisnum ? ConsoleColor.Green : ConsoleColor.Red;
                var timeused = timer.Stop();
                totaltime += timeused;
                string info = String.Format("{0} {1}ms\t", filename, timeused);
                //foreach (var m in bestmatches.Take(4)) {
                foreach (var m in kmresults.Take(4))
                {
                    info += String.Format("{0}/{1:F2}\t", templatenums[m.Index], m.Value);
                }
                //Debug(info);
                if (firstmatch != thisnum)
                {
                    Console.Write(".");
                }
                Console.ForegroundColor = fc;

                if (firstmatch == thisnum)
                {
                    ++acc;
                }
            }
            Debug("\nRSC and KM 测试用例:{0}。正确率{1}。", testcase, acc);

            Console.WriteLine("总用时:{0}ms,平均用时:{1}ms。", totaltime, totaltime / testcase);
            #endregion
        }
Beispiel #8
0
        public void Run()
        {
            double totaltime = 0;

            int s = 100, r = 5;

            string[] templatefiles = Directory.GetFiles(@"D:\Play Data\train_data\sc\", "*.sc")
                                     .Take(100).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];
                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(1000).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;
                var timeused = timer.Stop();
                totaltime += timeused;
                string info = String.Format("{0} {1}ms - {2}\t", filename, timeused, (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);
                if (firstmatch != thisnum)
                {
                    Console.Write(".");
                }
                Console.ForegroundColor = fc;

                if (firstmatch == thisnum)
                {
                    ++acc;
                }
            }
            Debug("\nRSC 测试用例:{0}。正确率{1}。", testcase, acc);

            Console.WriteLine("总用时:{0}ms,平均用时:{1}ms。", totaltime, totaltime / testcase);
            #endregion
        }
Beispiel #9
0
        public void Run()
        {
            double totaltime = 0;

            int s = 100, r = 5;

            string[] templatefiles = Directory.GetFiles(@"D:\Play Data\train_data\sc\", "*.sc")
                .Take(100).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];
                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(1000).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 knn = 10;

                #region 进行精细匹配
                var kmresults = new List<ValueIndexPair<double>>();
                foreach (var pair in arr.Take(knn)) {
                    int idx = pair.Index;
                    var costmat = Jim.OCR.ShapeContext2D.ShapeContext.HistCost(templates[idx], sc100);

                    var costmat_int = new int[s, s];
                    for (int ii = 0; ii < s; ++ii) {
                        for (int jj = 0; jj < s; ++jj) {
                            costmat_int[ii, jj] = (int)(costmat[ii, jj] * 10000);
                        }
                    }
                    var km = new KM(s, costmat_int);
                    km.Match(false);

                    kmresults.Add(new ValueIndexPair<double> { Index = idx, Value = km.MatchResult / 10000.0 });
                }
                kmresults.Sort((a, b) => a.Value.CompareTo(b.Value));
                #endregion

                //int firstmatch = match[0].Num;
                int firstmatch = templatenums[kmresults[0].Index];
                var fc = Console.ForegroundColor;
                Console.ForegroundColor = firstmatch == thisnum ? ConsoleColor.Green : ConsoleColor.Red;
                var timeused = timer.Stop();
                totaltime += timeused;
                string info = String.Format("{0} {1}ms\t", filename, timeused);
                //foreach (var m in bestmatches.Take(4)) {
                foreach (var m in kmresults.Take(4)) {
                    info += String.Format("{0}/{1:F2}\t", templatenums[m.Index], m.Value);
                }
                //Debug(info);
                if (firstmatch != thisnum) Console.Write(".");
                Console.ForegroundColor = fc;

                if (firstmatch == thisnum) {
                    ++acc;
                }
            }
            Debug("\nRSC and KM 测试用例:{0}。正确率{1}。", testcase, acc);

            Console.WriteLine("总用时:{0}ms,平均用时:{1}ms。", totaltime, totaltime / testcase);
            #endregion
        }
Beispiel #10
0
        private void recognize_rsc()
        {
            if (template_histograms == null) {
                MessageBox.Show("尚未读取模板。");
                return;
            }
            new Thread(new ThreadStart(() => {
                clearLog();
                showStatus("搜索中");
                foreach (var challenge in splitted_chars) {
                    timer.Restart();
                    var list = challenge.getEdge().Sample(100);

                    #region 计算形状上下文
                    int r = 15;
                    var scall = Jim.OCR.ShapeContext2D.ShapeContext.ComputeSC(list);
                    var scq = new double[r, 60];
                    for (int i = 0; i < r; ++i) {
                        int pos = rand.Next(list.Count);
                        for (int k = 0; k < 60; ++k) {
                            scq[i, k] = scall[pos, k];
                        }
                    }
                    #endregion
                    #region 计算距离
                    var dists = new ValueIndexPair<double>[template_sc.Length];
                    for (int i = 0; i < template_sc.Length; ++i) {
                        double[,] sci = template_sc[i];
                        double[,] costmat = Jim.OCR.ShapeContext2D.ShapeContext.HistCost(scq, sci);
                        double cost = 0;
                        for (int j = 0; j < r; ++j) {
                            double min = double.MaxValue;
                            for (int u = 0; u < 100; ++u) {
                                double val = costmat[j, u];
                                if (val < min) min = val;
                            }
                            cost += min;
                        }
                        dists[i] = new ValueIndexPair<double> { Value = cost, Index = i };
                        showProgress((i + 1.0) / template_histograms.Length);
                    }
                    #endregion

                    #region 对结果排序
                    var arr = dists
                        .OrderBy(p => p.Value)
                        .Select(p => new { Distance = p.Value, Char = template_chars[p.Index] })
                        //.Where(p => "ABCDEFGHIJKLMNPQRSTUVWXYZ123456789".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();
                    string result = "";
                    foreach (var m in match.Take(3)) {
                        result += String.Format("Char:'{0}',Accuracy:{1}/{2}\t", m.Ch, m.Count, knn);
                    }
                    appendLine(result);
                    #endregion
                }
                appendLine("-----------------------------------------------------");
                showStatus("搜索完成,共用时{0}ms。", timer.Stop());
            })).Start();
        }
Beispiel #11
0
        private void recognize_rsc()
        {
            if (template_histograms == null)
            {
                MessageBox.Show("尚未读取模板。");
                return;
            }
            new Thread(new ThreadStart(() => {
                clearLog();
                showStatus("搜索中");
                foreach (var challenge in splitted_chars)
                {
                    timer.Restart();
                    var list = challenge.getEdge().Sample(100);

                    #region 计算形状上下文
                    int r     = 15;
                    var scall = Jim.OCR.ShapeContext2D.ShapeContext.ComputeSC(list);
                    var scq   = new double[r, 60];
                    for (int i = 0; i < r; ++i)
                    {
                        int pos = rand.Next(list.Count);
                        for (int k = 0; k < 60; ++k)
                        {
                            scq[i, k] = scall[pos, k];
                        }
                    }
                    #endregion
                    #region 计算距离
                    var dists = new ValueIndexPair <double> [template_sc.Length];
                    for (int i = 0; i < template_sc.Length; ++i)
                    {
                        double[,] sci     = template_sc[i];
                        double[,] costmat = Jim.OCR.ShapeContext2D.ShapeContext.HistCost(scq, sci);
                        double cost       = 0;
                        for (int j = 0; j < r; ++j)
                        {
                            double min = double.MaxValue;
                            for (int u = 0; u < 100; ++u)
                            {
                                double val = costmat[j, u];
                                if (val < min)
                                {
                                    min = val;
                                }
                            }
                            cost += min;
                        }
                        dists[i] = new ValueIndexPair <double> {
                            Value = cost, Index = i
                        };
                        showProgress((i + 1.0) / template_histograms.Length);
                    }
                    #endregion

                    #region 对结果排序
                    var arr = dists
                              .OrderBy(p => p.Value)
                              .Select(p => new { Distance = p.Value, Char = template_chars[p.Index] })
                              //.Where(p => "ABCDEFGHIJKLMNPQRSTUVWXYZ123456789".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();
                    string result = "";
                    foreach (var m in match.Take(3))
                    {
                        result += String.Format("Char:'{0}',Accuracy:{1}/{2}\t", m.Ch, m.Count, knn);
                    }
                    appendLine(result);
                    #endregion
                }
                appendLine("-----------------------------------------------------");
                showStatus("搜索完成,共用时{0}ms。", timer.Stop());
            })).Start();
        }
Beispiel #12
0
        public void Run()
        {
            double totaltime = 0;

            int s = 100, r = 5;

            string[] templatefiles = Directory.GetFiles(@"D:\Play Data\train_data\sc\", "*.sc")
                .Take(100).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];
                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 scq = Jim.OCR.ShapeContext2D.ShapeContext.ComputeSC(list);

                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);

                    var costmat_int = new int[s, s];
                    for (int ii = 0; ii < s; ++ii) {
                        for (int jj = 0; jj < s; ++jj) {
                            costmat_int[ii, jj] = (int)(costmat[ii, jj] * 10000);
                        }
                    }
                    var km = new KM(s, costmat_int);
                    km.Match(false);
                    arr[i] = new ValueIndexPair<double> { Index = i, Value = km.MatchResult / 10000.0 };
                }
                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;
                var timeused = timer.Stop();
                totaltime += timeused;
                string info = String.Format("{0} {1}ms - {2}\t", filename, timeused, (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);

            Console.WriteLine("总用时:{0}ms,平均用时:{1}ms。", totaltime, totaltime / testcase);
            #endregion
        }