A class for checking simple geometrical shapes.

The class performs checking/detection of some simple geometrical shapes for provided set of points (shape's edge points). During the check the class goes through the list of all provided points and checks how accurately they fit into assumed shape.

All the shape checks allow some deviation of points from the shape with assumed parameters. In other words it is allowed that specified set of points may form a little bit distorted shape, which may be still recognized. The allowed amount of distortion is controlled by two properties (MinAcceptableDistortion and RelativeDistortionLimit), which allow higher distortion level for bigger shapes and smaller amount of distortion for smaller shapes. Checking specified set of points, the class calculates mean distance between specified set of points and edge of the assumed shape. If the mean distance is equal to or less than maximum allowed distance, then a shape is recognized. The maximum allowed distance is calculated as: maxDistance = max( minAcceptableDistortion, relativeDistortionLimit * ( width + height ) / 2 ) , where width and height is the size of bounding rectangle for the specified points.

See also AngleError and LengthError properties, which set acceptable errors for polygon sub type checking done by CheckPolygonSubType method.

See the next article for details about the implemented algorithms: Detecting some simple shapes in images.

Sample usage:

private List<IntPoint> idealCicle = new List<IntPoint>( ); private List<IntPoint> distorredCircle = new List<IntPoint>( ); System.Random rand = new System.Random( ); // generate sample circles float radius = 100; for ( int i = 0; i < 360; i += 10 ) { float angle = (float) ( (float) i / 180 * System.Math.PI ); // add point to ideal circle idealCicle.Add( new IntPoint( (int) ( radius * System.Math.Cos( angle ) ), (int) ( radius * System.Math.Sin( angle ) ) ) ); // add a bit distortion for distorred cirlce float distorredRadius = radius + rand.Next( 7 ) - 3; distorredCircle.Add( new IntPoint( (int) ( distorredRadius * System.Math.Cos( angle ) ), (int) ( distorredRadius * System.Math.Sin( angle ) ) ) ); } // check shape SimpleShapeChecker shapeChecker = new SimpleShapeChecker( ); if ( shapeChecker.IsCircle( idealCicle ) ) { // ... } if ( shapeChecker.CheckShapeType( distorredCircle ) == ShapeType.Circle ) { // ... }
示例#1
0
        public void CalculateShapes()
        {
            circles.Clear();
            triangles.Clear();
            quadrilaterals.Clear();
            polylines.Clear();

            CalculateBlobs();

            Ag.SimpleShapeChecker shapeChecker = new Ag.SimpleShapeChecker();

            if (Angle >= 0)
            {
                shapeChecker.AngleError = (float)Angle;
            }
            if (Length >= 0)
            {
                shapeChecker.LengthError = (float)Length;
            }
            if (Distortion >= 0)
            {
                shapeChecker.MinAcceptableDistortion = (float)Distortion;
            }

            foreach (Blob blob in blobObjects)
            {
                List <Accord.IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blob);

                Accord.Point center;
                float        radius;

                if (shapeChecker.IsCircle(edgePoints, out center, out radius))
                {
                    circles.Add(new Rg.Circle(Rg.Plane.WorldXY, center.ToRhPoint(bitmap.Height), radius).ToNurbsCurve());
                }
                else
                {
                    List <Accord.IntPoint> corners;
                    if (edgePoints.Count > 2)
                    {
                        if (shapeChecker.IsConvexPolygon(edgePoints, out corners))
                        {
                            if (shapeChecker.IsTriangle(edgePoints))
                            {
                                triangles.Add(corners.ToRhinoPoints(bitmap.Height).ToPolyline(true).ToNurbsCurve());
                            }
                            else if (shapeChecker.IsQuadrilateral(edgePoints))
                            {
                                quadrilaterals.Add(corners.ToRhinoPoints(bitmap.Height).ToPolyline(true).ToNurbsCurve());
                            }
                            else
                            {
                                polylines.Add(corners.ToRhinoPoints(bitmap.Height).ToPolyline(true).ToNurbsCurve());
                            }
                        }
                    }
                }
            }
        }
示例#2
0
        // Process image
        private void ProcessImage(Bitmap bitmap)
        {
            // lock image
            BitmapData bitmapData = bitmap.LockBits(
                new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                ImageLockMode.ReadWrite, bitmap.PixelFormat);

            // step 1 - turn background to black
            ColorFiltering colorFilter = new ColorFiltering();

            colorFilter.Red = new IntRange(0, 64);
            colorFilter.Green = new IntRange(0, 64);
            colorFilter.Blue = new IntRange(0, 64);
            colorFilter.FillOutsideRange = false;

            colorFilter.ApplyInPlace(bitmapData);

            // step 2 - locating objects
            BlobCounter blobCounter = new BlobCounter();

            blobCounter.FilterBlobs = true;
            blobCounter.MinHeight = 5;
            blobCounter.MinWidth = 5;

            blobCounter.ProcessImage(bitmapData);
            Blob[] blobs = blobCounter.GetObjectsInformation();
            bitmap.UnlockBits(bitmapData);

            // step 3 - check objects' type and highlight
            SimpleShapeChecker shapeChecker = new SimpleShapeChecker();

            Graphics g = Graphics.FromImage(bitmap);
            Pen yellowPen = new Pen(Color.Yellow, 2); // circles
            Pen redPen = new Pen(Color.Red, 2);       // quadrilateral
            Pen brownPen = new Pen(Color.Brown, 2);   // quadrilateral with known sub-type
            Pen greenPen = new Pen(Color.Green, 2);   // known triangle
            Pen bluePen = new Pen(Color.Blue, 2);     // triangle

            for (int i = 0, n = blobs.Length; i < n; i++)
            {
                List<IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blobs[i]);

                Accord.Point center;
                float radius;

                // is circle ?
                if (shapeChecker.IsCircle(edgePoints, out center, out radius))
                {
                    g.DrawEllipse(yellowPen,
                        (float)(center.X - radius), (float)(center.Y - radius),
                        (float)(radius * 2), (float)(radius * 2));
                }
                else
                {
                    List<IntPoint> corners;

                    // is triangle or quadrilateral
                    if (shapeChecker.IsConvexPolygon(edgePoints, out corners))
                    {
                        // get sub-type
                        PolygonSubType subType = shapeChecker.CheckPolygonSubType(corners);

                        Pen pen;

                        if (subType == PolygonSubType.Unknown)
                        {
                            pen = (corners.Count == 4) ? redPen : bluePen;
                        }
                        else
                        {
                            pen = (corners.Count == 4) ? brownPen : greenPen;
                        }

                        g.DrawPolygon(pen, ToPointsArray(corners));
                    }
                }
            }

            yellowPen.Dispose();
            redPen.Dispose();
            greenPen.Dispose();
            bluePen.Dispose();
            brownPen.Dispose();
            g.Dispose();

            // put new image to clipboard
            Clipboard.SetDataObject(bitmap);
            // and to picture box
            pictureBox.Image = bitmap;

            UpdatePictureBoxPosition();
        }