Border following algorithm for contour extraction.
Inheritance: IContourExtractionAlgorithm
Example #1
0
        public void FindPeaksTest()
        {
            Bitmap hand = Properties.Resources.rhand;

            GaussianBlur median = new GaussianBlur(1.1);
            median.ApplyInPlace(hand);

            // Extract contour
            BorderFollowing bf = new BorderFollowing(1);
            List<IntPoint> contour = bf.FindContour(hand);

            hand = hand.Clone(new Rectangle(0, 0, hand.Width, hand.Height), PixelFormat.Format24bppRgb);

            // Find peaks
            KCurvature kcurv = new KCurvature(30, new DoubleRange(0, 45));
            // kcurv.Suppression = 30;
            var peaks = kcurv.FindPeaks(contour);

            List<IntPoint> supports = new List<IntPoint>();
            for (int i = 0; i < peaks.Count; i++)
            {
                int j = contour.IndexOf(peaks[i]);
                supports.Add(contour[(j + kcurv.K) % contour.Count]);
                supports.Add(contour[Accord.Math.Tools.Mod(j - kcurv.K, contour.Count)]);
            }

            // show(hand, contour, peaks, supports);

            Assert.AreEqual(2, peaks.Count);
            Assert.AreEqual(46, peaks[0].X);
            Assert.AreEqual(0, peaks[0].Y);
            Assert.AreEqual(2, peaks[1].X);
            Assert.AreEqual(11, peaks[1].Y);
        }
        /// <summary>
        /// Extracts the contour from a single object in a grayscale image. (uses Accord built-in function)
        /// </summary>
        /// <param name="im">Image.</param>
        /// <param name="minGradientStrength">The pixel value threshold above which a pixel
        /// is considered black (belonging to the object). Default is zero.</param>
        public static List<Point> FindContour(this Gray<byte>[,] im, byte minGradientStrength = 0)
        {
            BorderFollowing bf = new BorderFollowing(minGradientStrength);

            List<Point> points;
            using (var uImg = im.Lock())
            {
                points = bf.FindContour(uImg.AsAForgeImage())
                           .Select(x => x.ToPoint())
                           .ToList();
            }

            return points;
        }
        public void FindDefectsTest()
        {

            Bitmap bmp = Properties.Resources.hand;

            Bitmap gray = AForge.Imaging.Filters.Grayscale.CommonAlgorithms.BT709.Apply(bmp);

            BlobCounter bc = new BlobCounter(gray);
            bc.ObjectsOrder = ObjectsOrder.Size;
            Blob[] blobs = bc.GetObjectsInformation();
            bc.ExtractBlobsImage(bmp, blobs[0], true);

            Bitmap blob = blobs[0].Image.ToManagedImage();

            BorderFollowing bf = new BorderFollowing();
            List<IntPoint> contour = bf.FindContour(blob);

            GrahamConvexHull graham = new GrahamConvexHull();
            List<IntPoint> hull = graham.FindHull(contour);

            ConvexHullDefects hullDefects = new ConvexHullDefects(10);
            List<ConvexityDefect> defects = hullDefects.FindDefects(contour, hull);

          /*  PointsMarker marker = new PointsMarker(hull, Color.Green, 10);
            marker.ApplyInPlace(blob);
            ImageBox.Show(blob);
            */

            Assert.AreEqual(2, defects.Count);
            Assert.AreEqual(new IntPoint(130, 10), contour[defects[0].Start]);
            Assert.AreEqual(new IntPoint(93, 109), contour[defects[0].Point]);
            Assert.AreEqual(new IntPoint(64, 9), contour[defects[0].End]);
            Assert.AreEqual(99.549179077148438, defects[0].Depth, 1e-5);
            Assert.IsFalse(double.IsNaN(defects[0].Depth));
            //    Assert.AreEqual(9912.9531239366424, defects[0].Area);

            Assert.AreEqual(new IntPoint(49, 18), contour[defects[1].Start]);
            Assert.AreEqual(new IntPoint(61, 106), contour[defects[1].Point]);
            Assert.AreEqual(new IntPoint(18, 127), contour[defects[1].End]);
            Assert.AreEqual(35.615153852366504, defects[1].Depth, 1e-5);
            Assert.IsFalse(double.IsNaN(defects[1].Depth));
            //    Assert.AreEqual(2293.7535682510002, defects[1].Area);

        }
        public void FindContourTest()
        {
            Bitmap bmp = Accord.Imaging.Image.Clone(Properties.Resources.sample_black);

            Bitmap gray = Grayscale.CommonAlgorithms.BT709.Apply(bmp);

            BlobCounter bc = new BlobCounter(gray);
            bc.ObjectsOrder = ObjectsOrder.Size;
            Blob[] blobs = bc.GetObjectsInformation();
            bc.ExtractBlobsImage(bmp, blobs[0], true);
            List<IntPoint> expected = bc.GetBlobsEdgePoints(blobs[0]);
            Bitmap blob = blobs[0].Image.ToManagedImage();

            BorderFollowing bf = new BorderFollowing();
            List<IntPoint> actual = bf.FindContour(blob);

            Assert.AreEqual(expected.Count, actual.Count);

            foreach (IntPoint point in expected)
                Assert.IsTrue(actual.Contains(point));

            foreach (IntPoint point in actual)
                Assert.IsTrue(expected.Contains(point));

            IntPoint prev = actual[0];
            for (int i = 1; i < actual.Count; i++)
            {
                IntPoint curr = actual[i];
                Assert.IsTrue(System.Math.Abs(prev.X - curr.X) <= 1 &&
                              System.Math.Abs(prev.Y - curr.Y) <= 1);
                prev = curr;
            }

            IntPoint first = actual[0];
            IntPoint last = actual[actual.Count - 1];
            Assert.IsTrue(System.Math.Abs(first.X - last.X) <= 1 &&
                          System.Math.Abs(first.Y - last.Y) <= 1);
        }
        public void FindContourTest3()
        {
            Bitmap image = Accord.Imaging.Image.Clone(Properties.Resources.sample_black);
            Bitmap grayscaleImage = Grayscale.CommonAlgorithms.BT709.Apply(image);

            // Create a new border following algorithm
            BorderFollowing borderFollowing = new BorderFollowing();

            // Get all points in the contour of the image. 
            List<IntPoint> contour = borderFollowing.FindContour(grayscaleImage);

            // Mark all points in the contour point list in blue
            new PointsMarker(contour, Color.Blue).ApplyInPlace(image);

            // Show the result
            // ImageBox.Show(image);

            Assert.AreEqual(380, contour.Count);
        }
        static void Main(string[] args)
        {
            Threshold thresh = new Threshold(10);
            Median median = new Median(9);
            Erosion3x3 erode = new Erosion3x3();
            Dilatation3x3 dilate = new Dilatation3x3();
            GrahamConvexHull hullFinder = new GrahamConvexHull();
            ConnectedComponentsLabeling ccLabeler = new ConnectedComponentsLabeling();
            BorderFollowing contourFinder = new BorderFollowing();
            GrayscaleToRGB rgb = new GrayscaleToRGB();
            ConvexHullDefects defectFinder = new ConvexHullDefects(10);

            Bitmap img = (Bitmap)Bitmap.FromFile("hand3.jpg");

            Bitmap image = Grayscale.CommonAlgorithms.BT709.Apply(img);
            thresh.ApplyInPlace(image);
            //median.ApplyInPlace(image);
            erode.ApplyInPlace(image);
            dilate.ApplyInPlace(image);

            BlobCounter counter = new BlobCounter(image);
            counter.ObjectsOrder = ObjectsOrder.Area;

            Blob[] blobs = counter.GetObjectsInformation();

            if (blobs.Length > 0)
            {
                counter.ExtractBlobsImage(image, blobs[0], true);

                UnmanagedImage hand = blobs[0].Image;

                var contour = contourFinder.FindContour(hand);

                if (contour.Count() > 0)
                {
                    var initialHull = hullFinder.FindHull(contour);

                    var defects = defectFinder.FindDefects(contour, initialHull);

                    var filteredHull = initialHull.ClusterHullPoints().FilterLinearHullPoints();

                    var palmCenter = defects.Centroid(contour);

                    var wristPoints = filteredHull.SelectWristPoints(defects, contour);

                    Bitmap color = rgb.Apply(hand).ToManagedImage();

                    //BitmapData data = color.LockBits(new Rectangle(0, 0, color.Width, color.Height), ImageLockMode.ReadWrite, color.PixelFormat);
                    //Drawing.Polyline(data, contour, Color.Blue);
                    //Drawing.Polygon(data, filteredHull, Color.Red);
                    //color.UnlockBits(data);

                    Graphics gr = Graphics.FromImage(color);

                    gr.DrawPolygon(new Pen(Brushes.Red, 3), filteredHull.ToPtArray());
                    gr.DrawLines(new Pen(Brushes.Blue, 3), contour.ToPtArray());
                    gr.DrawEllipse(new Pen(Brushes.Red, 3), palmCenter.X - 10, palmCenter.Y - 10, 20, 20);

                    foreach (ConvexityDefect defect in defects)
                    {
                        gr.DrawEllipse(new Pen(Brushes.Green, 6), contour[defect.Point].X - 10, contour[defect.Point].Y - 10, 20, 20);
                    }

                    foreach (AForge.IntPoint pt in filteredHull)
                    {
                        gr.DrawEllipse(new Pen(Brushes.Yellow, 6), pt.X - 10, pt.Y - 10, 20, 20);
                    }

                    foreach (AForge.IntPoint pt in wristPoints)
                    {
                        gr.DrawEllipse(new Pen(Brushes.PowderBlue, 6), pt.X - 10, pt.Y - 10, 20, 20);
                    }

                    ImageBox.Show(color);
                }
            }
        }
        public void FindContourTest2()
        {
            Bitmap bmp = Properties.Resources.hand2;

            BlobCounter bc = new BlobCounter(bmp);
            bc.ObjectsOrder = ObjectsOrder.Size;
            Blob[] blobs = bc.GetObjectsInformation();
            bc.ExtractBlobsImage(bmp, blobs[0], true);
            List<IntPoint> expected = bc.GetBlobsEdgePoints(blobs[0]);
            Bitmap blob = blobs[0].Image.ToManagedImage();

            BorderFollowing bf = new BorderFollowing();
            List<IntPoint> actual = bf.FindContour(blob);

            foreach (IntPoint point in expected)
                Assert.IsTrue(actual.Contains(point));

            IntPoint prev = actual[0];
            for (int i = 1; i < actual.Count; i++)
            {
                IntPoint curr = actual[i];
                Assert.IsTrue(System.Math.Abs(prev.X - curr.X) <= 1 &&
                              System.Math.Abs(prev.Y - curr.Y) <= 1);
                prev = curr;
            }

            IntPoint first = actual[0];
            IntPoint last = actual[actual.Count - 1];
            Assert.IsTrue(System.Math.Abs(first.X - last.X) <= 1 &&
                          System.Math.Abs(first.Y - last.Y) <= 1);
        }
 /// <summary>
 /// Extracts the contour from a single object in a grayscale image. (uses Accord built-in function)
 /// </summary>
 /// <param name="im">Image.</param>
 /// <param name="minGradientStrength">The pixel value threshold above which a pixel
 /// is considered black (belonging to the object). Default is zero.</param>
 public static List<Point> FindContour(this Image<Gray, byte> im, byte minGradientStrength = 0)
 {
     BorderFollowing bf = new BorderFollowing(minGradientStrength);
     return bf.FindContour(im.ToAForgeImage(copyAlways: false, failIfCannotCast: true));
 }