Opening operator from Mathematical Morphology.

Opening morphology operator equals to erosion followed by dilatation.

Applied to binary image, the filter may be used for removing small object keeping big objects unchanged. Since erosion is used first, it removes all small objects. Then dilatation restores big objects, which were not removed by erosion.

See documentation to Erosion and Dilatation classes for more information and list of supported pixel formats.

Sample usage:

// create filter Opening filter = new Opening( ); // apply the filter filter.Apply( image );

Initial image:

Result image:

Inheritance: IFilter, IInPlaceFilter, IInPlacePartialFilter, IFilterInformation
Exemplo n.º 1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="TopHat"/> class.
 /// </summary>
 ///
 /// <param name="se">Structuring element to pass to <see cref="Opening"/> operator.</param>
 ///
 public TopHat(short[,] se) : this()
 {
     opening = new Opening(se);
 }
Exemplo n.º 2
0
        public void GetBlobs2(string inputFile, string outputPath)
        {
            UnmanagedImage skewedImg = null;
            UnmanagedImage bwInvImg  = null;

            {
                var    bmp          = new Bitmap(inputFile);
                var    img          = UnmanagedImage.FromManagedImage(bmp);
                var    grayImg      = Accord.Imaging.Filters.Grayscale.CommonAlgorithms.BT709.Apply(img);
                var    bwImg        = new Accord.Imaging.Filters.OtsuThreshold().Apply(grayImg);
                var    skewChecker  = new DocumentSkewChecker();
                double angle        = skewChecker.GetSkewAngle(bwImg);
                var    rotateFilter = new Accord.Imaging.Filters.RotateBilinear(-angle);
                skewedImg = rotateFilter.Apply(img);
                bwImg.Dispose();
                grayImg.Dispose();
                img.Dispose();
                bmp.Dispose();
            }

            {
                var grayImg       = Accord.Imaging.Filters.Grayscale.CommonAlgorithms.BT709.Apply(skewedImg);
                var bwImg         = new Accord.Imaging.Filters.OtsuThreshold().Apply(grayImg);
                var openingFilter = new Accord.Imaging.Filters.Opening();
                openingFilter.ApplyInPlace(bwImg);
                bwInvImg = new Accord.Imaging.Filters.Invert().Apply(bwImg);
                bwImg.Dispose();
                grayImg.Dispose();
            }


            var blobProc = new Accord.Imaging.BlobCounter();

            blobProc.ProcessImage(bwInvImg);
            var blobs = blobProc.GetObjectsInformation().ToList();

            foreach (Accord.Imaging.Blob blob in blobs.OrderBy(b => b.Rectangle.Left).ThenBy(b => b.Rectangle.Top))
            {
                Console.WriteLine("{0} {1}", blob.Rectangle.ToString(), blob.Area.ToString());
            }

            //Layout parameters
            var expectedLineMarkerSize = new System.Drawing.Size(25, 10); //new System.Drawing.Size(35, 15);
            var expectedCellSize       = new System.Drawing.Size(15, 10); //new System.Drawing.Size(20, 13);
            int expectedNumlineMarkers = 19;                              // 23;
            int tolerance = 3;
            //Limits to determine in a cell is marked
            double fullnessOk     = .75;
            double fullnessUnsure = .65;
            var    questions      = new List <Tuple <int, Accord.Imaging.Blob, List <Accord.Imaging.Blob> > >();

            {
                var lineMarkers = blobs.Where(b =>
                {
                    if (b.Rectangle.Width < expectedLineMarkerSize.Width - tolerance)
                    {
                        return(false);
                    }
                    if (b.Rectangle.Width > expectedLineMarkerSize.Width + tolerance)
                    {
                        return(false);
                    }
                    if (b.Rectangle.Height < expectedLineMarkerSize.Height - tolerance)
                    {
                        return(false);
                    }
                    if (b.Rectangle.Height > expectedLineMarkerSize.Height + tolerance)
                    {
                        return(false);
                    }
                    return(true);
                })
                                  .OrderBy(b => b.Rectangle.Left)
                                  .ThenBy(b => b.Rectangle.Top)
                                  .ToList();
                if (lineMarkers.Count() != expectedNumlineMarkers)
                {
                    throw new Exception(string.Format("Can't locate all line markers. Expected {0}, found {1}", expectedNumlineMarkers, lineMarkers.Count));
                }
                var cells = blobs.Where(b =>
                {
                    if (b.Rectangle.Width < expectedCellSize.Width - tolerance)
                    {
                        return(false);
                    }
                    if (b.Rectangle.Width > expectedCellSize.Width + tolerance)
                    {
                        return(false);
                    }
                    if (b.Rectangle.Height < expectedCellSize.Height - tolerance)
                    {
                        return(false);
                    }
                    if (b.Rectangle.Height > expectedCellSize.Height + tolerance)
                    {
                        return(false);
                    }
                    return(true);
                }).ToList();

                int idxLine = 1;
                foreach (var lineMarker in lineMarkers.OrderBy(b => b.CenterOfGravity.Y))
                {
                    var cellsOfLine = cells.Where(b => Math.Abs(b.CenterOfGravity.Y - lineMarker.CenterOfGravity.Y) <= tolerance)
                                      .Take(5)
                                      .ToList()
                                      .OrderBy(b => b.CenterOfGravity.X)
                                      .ToList();
                    questions.Add(new Tuple <int, Accord.Imaging.Blob, List <Accord.Imaging.Blob> >(idxLine, lineMarker, cellsOfLine));
                    idxLine++;
                }
            }

            {
                var bmp = skewedImg.ToManagedImage();
                using (Graphics g = Graphics.FromImage(bmp))
                {
                    foreach (var question in questions)
                    {
                        g.FillRectangle(new SolidBrush(Color.Blue), question.Item2.Rectangle);
                        g.DrawString(question.Item1.ToString(), new System.Drawing.Font("Arial", 8), new SolidBrush(Color.White), question.Item2.Rectangle);
                        int column = 1;
                        foreach (Accord.Imaging.Blob blob in question.Item3.OrderBy(b => b.Rectangle.Left).ThenBy(b => b.Rectangle.Top))
                        {
                            if (System.Diagnostics.Debugger.IsAttached)
                            {
                                Console.WriteLine("Line {0}, Column {1}, Fullness {2}", question.Item1, column, Math.Round(blob.Fullness, 2));
                            }
                            if (blob.Fullness >= fullnessOk)
                            {
                                g.DrawRectangle(new Pen(Color.Green, 2), blob.Rectangle);
                            }
                            else if (blob.Fullness >= fullnessUnsure)
                            {
                                g.DrawRectangle(new Pen(Color.Yellow, 2), blob.Rectangle);
                            }
                            else
                            {
                                g.DrawRectangle(new Pen(Color.Red, 2), blob.Rectangle);
                            }
                            column++;
                        }
                    }
                }
                // bmp.Save(outp);
            }
        }
Exemplo n.º 3
0
 private void SetFilter()
 {
     ImageType = ImageTypes.Rgb24bpp;
     Af.Opening newFilter = new Af.Opening();
     imageFilter = newFilter;
 }
Exemplo n.º 4
0
 /// <summary>
 /// Initializes a new instance of the <see cref="TopHat"/> class.
 /// </summary>
 /// 
 /// <param name="se">Structuring element to pass to <see cref="Opening"/> operator.</param>
 /// 
 public TopHat( short[,] se ) : this( )
 {
     opening = new Opening( se );
 }