Esempio n. 1
0
        private void button1_Click(object sender, EventArgs e)
        {
            List <int> rows = new List <int>();
            List <int> cols = new List <int>();
            Bitmap     bmp  = (Bitmap)Image.FromFile("Sudoku.png");

            if (bmp.PixelFormat == PixelFormat.Format32bppArgb)
            {
                ImageUtility.ARGB2Gray(ref bmp);
            }
            else if (bmp.PixelFormat == PixelFormat.Format24bppRgb)
            {
                ImageUtility.RGB2Gray(ref bmp);
            }
            ImageUtility.Gray2Mono(ref bmp, 30);
            BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);
            int        length  = bmpData.Stride * bmp.Height;

            byte[] byteData = new byte[length];
            System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, byteData, 0, length);
            bmp.UnlockBits(bmpData);
            for (int j = 0; j < bmp.Height; j++)
            {
                for (int i = 0; i < bmp.Width; i++)
                {
                    byte b = byteData[j * bmpData.Stride + i];
                    if (b < 128)
                    {
                        if (!rows.Contains(j))
                        {
                            rows.Add(j);
                        }
                        if (!cols.Contains(i))
                        {
                            cols.Add(i);
                        }
                    }
                }
            }
            rows.Sort();
            cols.Sort();
            Dictionary <int, List <int> > rowData = new Dictionary <int, List <int> >();
            Dictionary <int, List <int> > colData = new Dictionary <int, List <int> >();
            int lastRow = 0;

            for (int i = 0; i < rows.Count - 1; i++)
            {
                int d = rows[i + 1] - rows[i];
                if (d > 1)
                {
                    rowData[rowData.Count + 1] = new List <int>();
                    for (int k = lastRow; k < i + 1; k++)
                    {
                        rowData[rowData.Count].Add(rows[k]);
                    }
                    lastRow = i + 1;
                }
            }
            rowData[rowData.Count + 1] = new List <int>();
            for (int k = lastRow; k < rows.Count; k++)
            {
                rowData[rowData.Count].Add(rows[k]);
            }

            // 去除干扰点的影响
            int rowSum = 0;

            foreach (var pair in rowData)
            {
                rowSum += pair.Value.Count();
            }
            int rowAvg = rowSum / rowData.Count;

            int[] rowKeys = rowData.Keys.ToArray();
            for (int i = 0; i < rowKeys.Length; i++)
            {
                if (rowData[rowKeys[i]].Count < rowAvg / 2)
                {
                    rowData.Remove(rowKeys[i]);
                }
            }
            rowKeys = rowData.Keys.ToArray();

            int lastCol = 0;

            for (int j = 0; j < cols.Count - 1; j++)
            {
                int d = cols[j + 1] - cols[j];
                if (d > 1)
                {
                    colData[colData.Count + 1] = new List <int>();
                    for (int k = lastCol; k < j + 1; k++)
                    {
                        colData[colData.Count].Add(cols[k]);
                    }
                    lastCol = j + 1;
                }
            }
            colData[colData.Count + 1] = new List <int>();
            for (int k = lastCol; k < cols.Count; k++)
            {
                colData[colData.Count].Add(cols[k]);
            }

            // 去除干扰点的影响
            int colSum = 0;

            foreach (var pair in colData)
            {
                colSum += pair.Value.Count();
            }
            int colAvg = colSum / colData.Count;

            int[] colKeys = colData.Keys.ToArray();
            for (int i = 0; i < colKeys.Length; i++)
            {
                if (colData[colKeys[i]].Count < colAvg / 2)
                {
                    colData.Remove(colKeys[i]);
                }
            }
            colKeys = colData.Keys.ToArray();

            // 计算数字中心点
            int margin = 8;

            int[] cxs = new int[colData.Count];
            int[] dxs = new int[colData.Count];
            for (int i = 0; i < colKeys.Length; i++)
            {
                List <int> lst = colData[colKeys[i]];
                cxs[i] = lst[lst.Count / 2];
                dxs[i] = lst[lst.Count - 1] - lst[0];
            }
            int dx = dxs.Max() + margin;

            int[] cys = new int[rowData.Count];
            int[] dys = new int[rowData.Count];
            for (int i = 0; i < rowKeys.Length; i++)
            {
                List <int> lst = rowData[rowKeys[i]];
                cys[i] = lst[lst.Count / 2];
                dys[i] = lst[lst.Count - 1] - lst[0];
            }
            int dy = dys.Max() + margin;

            _sudoku.Reset();
            Bitmap img = bmp;

            for (int j = 0; j < dys.Length; j++)
            {
                for (int i = 0; i < dxs.Length; i++)
                {
                    ImageFormat imageFormat = ImageFormat.Png;
                    string      filename    = $"{i + 1}-{j + 1}.{imageFormat.ToString().ToLower()}";
                    Bitmap      sub         = img.Clone(new Rectangle(cxs[i] - dx / 2, cys[j] - dy / 2, dx, dy), bmp.PixelFormat);
                    sub.Save(filename, imageFormat);
                    int value = OcrUtility.Instance.OCR(sub);
                    //int value = OcrUtility.Instance.OCRByCmd(filename);
                    if (value > 0)
                    {
                        _sudoku.GetItem(i, j).SetValue(value);
                    }
                    else if (value == 0)
                    {
                        Console.WriteLine($"OCR error:{i + 1}-{j + 1}");
                    }
                }
            }
            img.Dispose();

            _sudoku.Print();
            _sudoku.SaveBy0("Sudoku.txt");

            string txt = _sudoku.Print2String();

            richTextBox.Text = txt;
        }