/// <summary> /// Clear blobs structure. (cvReleaseBlobs) /// </summary> /// <param name="blobs">List of blobs.</param> public static void ReleaseBlobs(CvBlobs blobs) { if (blobs == null) throw new ArgumentNullException("blobs"); blobs.Dispose(); }
//############################################################################################################################################################################################## /// <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; } }