Beispiel #1
0
    /// <summary>
    /// The main working method. Handles the flow from creating a bitmap
    /// from the scanned image to analysing its digits and solving the sudoku.
    /// </summary>
    /// <param name="pixels">The scanned image as a one-dimensional array of Colors.</param>
    public void Worker(Color[] pixels)
    {
        try
        {
            var timer = System.Diagnostics.Stopwatch.StartNew();
            //cut out the sudoku part
            pixels = ArrayHandling.Cut(pixels, textureWidth, textureHeight,
                                       (textureWidth - side) / 2, (textureHeight - side) / 2, side, side);

            Status = "Creating Bitmap";                                                 //the current status is displayed while the background thread is active
            bool[] bits = Bitify(pixels, side, side, HorizontalChunks, VerticalChunks); //generate a "black-and-white" bitmap from the picture

            int[] coords;
            int   searchRadius;
            Status = "Finding Corners";

            int[][] corners = OCR.FindCorners2(bits, side, side, CornerQueueLength); //find the corners of the sudoku
            if (corners == null)
            {
                Popup.queued = new KeyValuePair <string, System.Action>(OCR.NoSudokuMessage, null);
                corners      = new int[][] { new int[] { 0, 0 }, new int[] { 0, 0 }, new int[] { 0, 0 }, new int[] { 0, 0 } };
            }

            #if WRITE_IMAGES_TO_DISK
            foreach (int[] corner in corners)
            {
                colorq.Enqueue(new KeyValuePair <int, Color>(corner[0] + corner[1] * side, Color.yellow));
            }
            #endif

            searchRadius = Mathf.RoundToInt(SearchRadiusFactor * Mathf.Sqrt(
                                                Mathf.Pow((corners[2][0] - corners[0][0]) / 9f, 2) +
                                                Mathf.Pow((corners[2][1] - corners[0][1]) / 9f, 2)
                                                ));

            Status = "Finding Digits";
            coords = OCR.FindDigitCoordinates(corners, side);             //calculate where the digits should be

            Status         = "Identifying Digits";
            unsolvedSudoku = OCR.GetSudoku(bits, side, side, coords, searchRadius, storedBitmaps, InstantMatchPercent, MaxStoredBitmapsPerDigit);             //identify all digits

            allZero = ArrayHandling.OnlyZeroes(unsolvedSudoku);

            var sb = new System.Text.StringBuilder();
            for (int y = 8; y >= 0; y--)
            {
                for (int x = 0; x < 9; x++)
                {
                    sb.Append(unsolvedSudoku[x, y]);
                }
                sb.AppendLine();
            }
            print(sb);

            Status       = "Solving Sudoku";
            solvedSudoku = ArrayHandling.Solve(unsolvedSudoku, ref success);             //solve the sudoku

            if (!success)
            {
                Popup.queued = new KeyValuePair <string, System.Action>(CannotSolveMessage, null);
            }

            sb = new System.Text.StringBuilder();
            for (int y = 8; y >= 0; y--)
            {
                for (int x = 0; x < 9; x++)
                {
                    sb.Append(solvedSudoku[x, y]);
                }
                sb.AppendLine();
            }
            print(sb);

            #if WRITE_IMAGES_TO_DISK
            Status = "Rendering Debug Picture";
            for (int i = 0; i < pixels.Length; i++)
            {
                pixels[i] = bits[i] ? Color.white : Color.black;
            }

            while (colorq.Count > 0)
            {
                var kvp = colorq.Dequeue();
                if (kvp.Key >= 0 && kvp.Key < pixels.Length)
                {
                    pixels[kvp.Key] = kvp.Value;
                }
            }
            #endif
            debugPicture = pixels;


            timer.Stop();
            print("Done");
            print("Time: " + timer.ElapsedMilliseconds + " ms");
            Status = StatusDone;             //signal to the main thread that the solved sudoku is availible
        }
        catch (System.Exception e)
        {
            print(e);
            Status = StatusError + e.Message;
        }
    }