Example #1
0
        //**********************************************************************************************************************************************************************************************

        public async Task Solve()
        {
            await Task.Run(() =>
            {
                try
                {
                    PuzzleSolutionImages.Clear();

                    compareAllEdges();

                    CurrentSolverState = PuzzleSolverState.SOLVE_PUZZLE;
                    CurrentSolverStepPercentageFinished = 0;
                    PuzzleDisjointSet p = new PuzzleDisjointSet(Pieces.Count);
                    p.JoinValidation    = JoinValidationFunction;

                    _logHandle.Report(new LogEventInfo("Join Pieces"));

                    for (int i = 0; i < matches.Count; i++)
                    {
                        if (_cancelToken.IsCancellationRequested)
                        {
                            _cancelToken.ThrowIfCancellationRequested();
                        }

                        CurrentSolverStepPercentageFinished = (i / (double)matches.Count) * 100;
                        if (p.InOneSet())
                        {
                            break;
                        }

                        int p1 = matches[i].PieceIndex1;
                        int e1 = matches[i].EdgeIndex1;
                        int p2 = matches[i].PieceIndex2;
                        int e2 = matches[i].EdgeIndex2;

                        p.JoinSets(p1, p2, e1, e2);
                    }

                    _logHandle.Report(new LogEventInfo("Possible solution found (" + p.SetCount.ToString() + " solutions)"));
                    CurrentSolverStepPercentageFinished = 100;
                    CurrentSolverState        = PuzzleSolverState.SOLVED;
                    CurrentSolutionNumber     = 0;
                    CurrentSolutionPieceIndex = 0;
                    int setNo = 0;
                    foreach (Forest jointSet in p.GetJointSets())
                    {
                        Matrix <int> solution           = jointSet.locations;
                        Matrix <int> solution_rotations = jointSet.rotations;

                        for (int i = 0; i < solution.Size.Width; i++)
                        {
                            for (int j = 0; j < solution.Size.Height; j++)
                            {
                                int piece_number = solution[j, i];
                                if (piece_number == -1)
                                {
                                    continue;
                                }
                                Pieces[piece_number].Rotate(4 - solution_rotations[j, i]);

                                Pieces[piece_number].SolutionRotation = solution_rotations[j, i] * 90;
                                Pieces[piece_number].SolutionLocation = new Point(i, j);
                                Pieces[piece_number].SolutionID       = setNo;
                            }
                        }
                        Solutions.Add(solution);
                        SolutionsRotations.Add(solution_rotations);

                        // Get the enabled Plugins for solution image generation
                        List <PluginGroupGenerateSolutionImage> pluginsGenerateSolutionImage = PluginFactory.GetEnabledPluginsOfGroupType <PluginGroupGenerateSolutionImage>();

                        foreach (PluginGroupGenerateSolutionImage plugin in pluginsGenerateSolutionImage)
                        {
                            PluginNameAttribute nameAttribute = plugin.GetType().GetCustomAttributes(false).Where(a => a.GetType() == typeof(PluginNameAttribute)).FirstOrDefault() as PluginNameAttribute;

                            Bitmap solutionImg = plugin.GenerateSolutionImage(solution, setNo, Pieces.ToList());
                            PuzzleSolutionImages.Add(new ImageDescribedLight("Solution #" + setNo.ToString() + " (" + nameAttribute.Name + ")", PuzzlePiecesFolderPath + @"\Results\Solutions\Solution#" + setNo.ToString() + ".png", solutionImg));

                            if (PluginFactory.GetGeneralSettingsPlugin().SolverShowDebugResults)
                            {
                                _logHandle.Report(new LogEventImage("Solution #" + setNo.ToString() + " (" + nameAttribute.Name + ")", solutionImg));
                            }
                            solutionImg.Dispose();
                        }
                        setNo++;
                    }
                }
                catch (OperationCanceledException)
                {
                    _logHandle.Report(new LogEventWarning("The operation was canceled. Step: " + CurrentSolverState.ToString()));
                    CurrentSolverState = PuzzleSolverState.UNSOLVED;
                }
                catch (Exception ex)
                {
                    _logHandle.Report(new LogEventError("The following error occured in step " + CurrentSolverState.ToString() + ":\n" + ex.Message));
                    CurrentSolverState = PuzzleSolverState.ERROR;
                    CurrentSolverStepPercentageFinished = 100;
                }
            }, _cancelToken);
        }
Example #2
0
        //##############################################################################################################################################################################################

        /// <summary>
        /// Extract all pieces from the source image.
        /// </summary>
        private void extract_pieces()
        {
            try
            {
                CurrentSolverState = PuzzleSolverState.INIT_PIECES;
                Piece.NextPieceID  = 0;
                CurrentSolverStepPercentageFinished = 0;
                _logHandle.Report(new LogEventInfo("Extracting Pieces"));
                NumberPuzzlePieces = 0;

                Pieces.Clear();
                InputImages.Clear();

                List <string> imageExtensions = new List <string>()
                {
                    ".jpg", ".png", ".bmp", ".tiff"
                };
                FileAttributes  attr           = File.GetAttributes(PuzzlePiecesFolderPath);
                List <FileInfo> imageFilesInfo = new List <FileInfo>();
                if (attr.HasFlag(FileAttributes.Directory))      //detect whether its a directory or file
                {
                    DirectoryInfo folderInfo = new DirectoryInfo(PuzzlePiecesFolderPath);
                    imageFilesInfo = folderInfo.GetFiles().ToList();
                }
                else
                {
                    FileInfo fileInfo = new FileInfo(PuzzlePiecesFolderPath);
                    imageFilesInfo.Add(fileInfo);
                }

                imageFilesInfo = imageFilesInfo.Where(f => imageExtensions.Contains(f.Extension)).ToList();

                int loopCount = 0;

                ParallelOptions parallelOptions = new ParallelOptions
                {
                    CancellationToken      = _cancelToken,
                    MaxDegreeOfParallelism = (PluginFactory.GetGeneralSettingsPlugin().UseParallelLoops ? Environment.ProcessorCount : 1)
                };
                //For each input image
                Parallel.For(0, imageFilesInfo.Count, parallelOptions, (i) =>
                {
                    using (Image <Rgba, byte> sourceImg = new Image <Rgba, byte>(imageFilesInfo[i].FullName)) //.LimitImageSize(1000, 1000))
                    {
                        CvInvoke.MedianBlur(sourceImg, sourceImg, 5);

                        // Get the (first) enabled Plugin for input image mask generation
                        PluginGroupInputImageMask pluginInputImageMask = PluginFactory.GetEnabledPluginsOfGroupType <PluginGroupInputImageMask>().FirstOrDefault();

                        using (Image <Gray, byte> mask = pluginInputImageMask.GetMask(sourceImg))
                        {
                            _logHandle.Report(new LogEventInfo("Extracting Pieces from source image " + i.ToString()));
                            if (PluginFactory.GetGeneralSettingsPlugin().SolverShowDebugResults)
                            {
                                _logHandle.Report(new LogEventImage("Source image " + i.ToString(), sourceImg.Bitmap));
                                _logHandle.Report(new LogEventImage("Mask " + i.ToString(), mask.Bitmap));
                            }

                            CvBlobDetector blobDetector = new CvBlobDetector();                 // Find all blobs in the mask image, extract them and add them to the list of pieces
                            CvBlobs blobs = new CvBlobs();
                            blobDetector.Detect(mask, blobs);

                            foreach (CvBlob blob in blobs.Values.Where(b => b.BoundingBox.Width >= PluginFactory.GetGeneralSettingsPlugin().PuzzleMinPieceSize&& b.BoundingBox.Height >= PluginFactory.GetGeneralSettingsPlugin().PuzzleMinPieceSize))
                            {
                                if (_cancelToken.IsCancellationRequested)
                                {
                                    _cancelToken.ThrowIfCancellationRequested();
                                }

                                Rectangle roi = blob.BoundingBox;

                                Image <Rgba, byte> pieceSourceImg;
                                Image <Gray, byte> pieceMask;

                                try
                                {
                                    if (sourceImg.Height > roi.Height + 4 && sourceImg.Width > roi.Width + 4)
                                    {
                                        roi.Inflate(2, 2);
                                    }
                                    pieceSourceImg = sourceImg.Copy(roi);
                                    pieceMask      = mask.Copy(roi);
                                }
                                catch (Exception)
                                {
                                    roi            = blob.BoundingBox;
                                    pieceSourceImg = sourceImg.Copy(roi);
                                    pieceMask      = mask.Copy(roi);
                                }

                                // Mask out background of piece
                                Image <Rgba, byte> pieceSourceImageForeground = new Image <Rgba, byte>(pieceSourceImg.Size);
                                CvInvoke.BitwiseOr(pieceSourceImg, pieceSourceImg, pieceSourceImageForeground, pieceMask);

                                Image <Gray, byte> pieceMaskInverted = pieceMask.Copy(pieceMask);
                                pieceMaskInverted._Not();
                                Image <Rgba, byte> background = new Image <Rgba, byte>(pieceSourceImg.Size);
                                background.SetValue(new Rgba(255, 255, 255, 0));
                                Image <Rgba, byte> pieceSourceImageBackground = new Image <Rgba, byte>(pieceSourceImg.Size);
                                CvInvoke.BitwiseOr(background, background, pieceSourceImageBackground, pieceMaskInverted);

                                Image <Rgba, byte> pieceSourceImgMasked = new Image <Rgba, byte>(pieceSourceImg.Size);
                                CvInvoke.BitwiseOr(pieceSourceImageForeground, pieceSourceImageBackground, pieceSourceImgMasked);

                                Piece p = new Piece(pieceSourceImgMasked, pieceMask, imageFilesInfo[i].FullName, roi.Location, _logHandle, _cancelToken);
                                lock (_piecesLock) { Pieces.Add(p); }

                                sourceImg.Draw(roi, new Rgba(255, 0, 0, 1), 2);
                                int baseLine  = 0;
                                Size textSize = CvInvoke.GetTextSize(p.PieceID.Replace("Piece", ""), FontFace.HersheyDuplex, 3, 2, ref baseLine);
                                CvInvoke.PutText(sourceImg, p.PieceID.Replace("Piece", ""), Point.Add(roi.Location, new Size(0, textSize.Height + 10)), FontFace.HersheyDuplex, 3, new MCvScalar(255, 0, 0), 2);

                                NumberPuzzlePieces++;

                                pieceSourceImg.Dispose();
                                pieceMask.Dispose();
                                pieceSourceImageForeground.Dispose();
                                pieceMaskInverted.Dispose();
                                background.Dispose();
                                pieceSourceImageBackground.Dispose();
                                pieceSourceImgMasked.Dispose();

                                GC.Collect();
                            }

                            Interlocked.Add(ref loopCount, 1);
                            CurrentSolverStepPercentageFinished = (loopCount / (double)imageFilesInfo.Count) * 100;

                            if (PluginFactory.GetGeneralSettingsPlugin().SolverShowDebugResults)
                            {
                                _logHandle.Report(new LogEventImage("Source Img " + i.ToString() + " Pieces", sourceImg.Bitmap));
                            }
                            InputImages.Add(new ImageDescribedLight(Path.GetFileName(imageFilesInfo[i].FullName), PuzzlePiecesFolderPath + @"\Results\InputImagesMarked\" + Path.GetFileName(imageFilesInfo[i].FullName), sourceImg.Bitmap)); //sourceImg.LimitImageSize(1000, 1000).Bitmap));
                            blobs.Dispose();
                            blobDetector.Dispose();
                            GC.Collect();
                        }
                    }

                    GC.Collect();
                    GC.WaitForPendingFinalizers();
                    GC.Collect();
                });

                Pieces.Sort(p => ((Piece)p).PieceIndex, null);
            }
            catch (OperationCanceledException)
            {
                _logHandle.Report(new LogEventWarning("The operation was canceled. Step: " + CurrentSolverState.ToString()));
                CurrentSolverState = PuzzleSolverState.UNSOLVED;
            }
            catch (Exception ex)
            {
                _logHandle.Report(new LogEventError("The following error occured in step " + CurrentSolverState.ToString() + ":\n" + ex.Message));
                CurrentSolverState = PuzzleSolverState.ERROR;
                CurrentSolverStepPercentageFinished = 100;
            }
        }