AForge.Math.Geometry.ClosePointsMergingOptimizer.OptimizeShape C# (CSharp) Method

OptimizeShape() public method

Optimize specified shape.
public OptimizeShape ( List shape ) : List
shape List Shape to be optimized.
return List
        public List<IntPoint> OptimizeShape( List<IntPoint> shape )
        {
            // optimized shape
            List<IntPoint> optimizedShape = new List<IntPoint>( );

            if ( shape.Count <= 3 )
            {
                // do nothing if shape has 3 points or less
                optimizedShape.AddRange( shape );
            }
            else
            {
                float distance = 0;

                // add first point to the new shape
                optimizedShape.Add( shape[0] );
                int pointsInOptimizedHull = 1;

                for ( int i = 1, n = shape.Count; i < n; i++ )
                {
                    distance = optimizedShape[pointsInOptimizedHull - 1].DistanceTo( shape[i] );

                    if ( ( distance <= maxDistanceToMerge ) &&
                         ( pointsInOptimizedHull + ( n - i ) > 3 ) )
                    {
                        // merge
                        optimizedShape[pointsInOptimizedHull - 1] = ( optimizedShape[pointsInOptimizedHull - 1] + shape[i] ) / 2;
                    }
                    else
                    {
                        optimizedShape.Add( shape[i] );
                        pointsInOptimizedHull++;
                    }
                }

                if ( pointsInOptimizedHull > 3 )
                {
                    // check the last and first points
                    distance = optimizedShape[pointsInOptimizedHull - 1].DistanceTo( optimizedShape[0] );

                    if ( distance <= maxDistanceToMerge )
                    {
                        // merge
                        optimizedShape[0] = ( optimizedShape[pointsInOptimizedHull - 1] + optimizedShape[0] ) / 2;
                        optimizedShape.RemoveAt( pointsInOptimizedHull - 1 );
                    }
                }
            }

            return optimizedShape;
        }
    }

Usage Example

Example #1
0
        // ==========================================================================================================
        // Components:
        // ==========================================================================================================
        private List<Shapes.Component> FindComponentsFunct(Bitmap bitmap)
        {
            // Locating objects
            BlobCounter blobCounter = new BlobCounter();
            blobCounter.FilterBlobs = true;
            blobCounter.MinHeight = 8;
            blobCounter.MinWidth = 8;
            blobCounter.ProcessImage(bitmap);
            Blob[] blobs = blobCounter.GetObjectsInformation();

            // create convex hull searching algorithm
            GrahamConvexHull hullFinder = new GrahamConvexHull();
            ClosePointsMergingOptimizer optimizer1 = new ClosePointsMergingOptimizer();
            FlatAnglesOptimizer optimizer2 = new FlatAnglesOptimizer();

            List<Shapes.Component> Components = new List<Shapes.Component>();

            // process each blob
            foreach (Blob blob in blobs)
            {
                List<IntPoint> leftPoints, rightPoints, edgePoints = new List<IntPoint>();
                if ((blob.Rectangle.Height > 400) && (blob.Rectangle.Width > 600))
                {
                    break;	// The whole image could be a blob, discard that
                }
                // get blob's edge points
                blobCounter.GetBlobsLeftAndRightEdges(blob,
                    out leftPoints, out rightPoints);

                edgePoints.AddRange(leftPoints);
                edgePoints.AddRange(rightPoints);

                // blob's convex hull
                List<IntPoint> Outline = hullFinder.FindHull(edgePoints);
                optimizer1.MaxDistanceToMerge = 4;
                optimizer2.MaxAngleToKeep = 170F;
                Outline = optimizer2.OptimizeShape(Outline);
                Outline = optimizer1.OptimizeShape(Outline);

                // find Longest line segment
                float dist = 0;
                LineSegment Longest = new LineSegment(Outline[0], Outline[1]);
                LineSegment line;
                dist = Longest.Length;
                int LongestInd = 0;
                for (int i = 1; i < Outline.Count; i++)
                {
                    if (i != Outline.Count - 1)
                    {
                        line = new LineSegment(Outline[i], Outline[i + 1]);
                    }
                    else
                    {
                        // last iteration
                        if (Outline[i] == Outline[0])
                        {
                            break;
                        }
                        line = new LineSegment(Outline[i], Outline[0]);
                    }
                    if (line.Length > dist)
                    {
                        Longest = line;
                        dist = line.Length;
                        LongestInd = i;
                    }
                }
                // Get the center point of it
                AForge.Point LongestCenter = new AForge.Point();
                LongestCenter.X = (float)Math.Round((Longest.End.X - Longest.Start.X) / 2.0 + Longest.Start.X);
                LongestCenter.Y = (float)Math.Round((Longest.End.Y - Longest.Start.Y) / 2.0 + Longest.Start.Y);
                AForge.Point NormalStart = new AForge.Point();
                AForge.Point NormalEnd = new AForge.Point();
                // Find normal:
                // start= longest.start rotated +90deg relative to center
                // end= longest.end rotated -90deg and relative to center
                // If you rotate point (px, py) around point (ox, oy) by angle theta you'll get:
                // p'x = cos(theta) * (px-ox) - sin(theta) * (py-oy) + ox
                // p'y = sin(theta) * (px-ox) + cos(theta) * (py-oy) + oy
                // cos90 = 0, sin90= 1 =>
                // p'x= -(py-oy) + ox= oy-py+ox, p'y= (px-ox)+ oy
                NormalStart.X = LongestCenter.Y - Longest.Start.Y + LongestCenter.X;
                NormalStart.Y = (Longest.Start.X - LongestCenter.X) + LongestCenter.Y;
                // cos-90=0, sin-90= -1 =>
                // p'x= (py-oy) + ox
                // p'y= -(px-ox)+oy= ox-px+oy
                NormalEnd.X = (Longest.Start.Y - LongestCenter.Y) + LongestCenter.X;
                NormalEnd.Y = LongestCenter.X - Longest.Start.X + LongestCenter.Y;
                // Make line out of the points
                Line Normal = Line.FromPoints(NormalStart, NormalEnd);

                // Find the furthest intersection to the normal (skip the Longest)
                AForge.Point InterSection = new AForge.Point();
                AForge.Point Furthest = new AForge.Point();
                bool FurhtestAssinged = false;
                LineSegment seg;
                dist = 0;
                for (int i = 0; i < Outline.Count; i++)
                {
                    if (i == LongestInd)
                    {
                        continue;
                    }
                    if (i != Outline.Count - 1)
                    {
                        seg = new LineSegment(Outline[i], Outline[i + 1]);
                    }
                    else
                    {
                        // last iteration
                        if (Outline[i] == Outline[0])
                        {
                            break;
                        }
                        seg = new LineSegment(Outline[i], Outline[0]);
                    }
                    if (seg.GetIntersectionWith(Normal) == null)
                    {
                        continue;
                    }
                    InterSection = (AForge.Point)seg.GetIntersectionWith(Normal);
                    if (InterSection.DistanceTo(LongestCenter) > dist)
                    {
                        Furthest = InterSection;
                        FurhtestAssinged = true;
                        dist = InterSection.DistanceTo(LongestCenter);
                    }
                }
                // Check, if there is a edge point that is close to the normal even further
                AForge.Point fPoint = new AForge.Point();
                for (int i = 0; i < Outline.Count; i++)
                {
                    fPoint.X = Outline[i].X;
                    fPoint.Y = Outline[i].Y;
                    if (Normal.DistanceToPoint(fPoint) < 1.5)
                    {
                        if (fPoint.DistanceTo(LongestCenter) > dist)
                        {
                            Furthest = fPoint;
                            FurhtestAssinged = true;
                            dist = fPoint.DistanceTo(LongestCenter);
                        }
                    }
                }
                AForge.Point ComponentCenter = new AForge.Point();
                if (FurhtestAssinged)
                {
                    // Find the midpoint of LongestCenter and Furthest: This is the centerpoint of component
                    ComponentCenter.X = (float)Math.Round((LongestCenter.X - Furthest.X) / 2.0 + Furthest.X);
                    ComponentCenter.Y = (float)Math.Round((LongestCenter.Y - Furthest.Y) / 2.0 + Furthest.Y);
                    // Alignment is the angle of longest
                    double Alignment;
                    if (Math.Abs(Longest.End.X - Longest.Start.X) < 0.001)
                    {
                        Alignment = 0;
                    }
                    else
                    {
                        Alignment = Math.Atan((Longest.End.Y - Longest.Start.Y) / (Longest.End.X - Longest.Start.X));
                        Alignment = Alignment * 180.0 / Math.PI; // in deg.
                    }
                    Components.Add(new Shapes.Component(ComponentCenter, Alignment, Outline, Longest, NormalStart, NormalEnd));
                }
            }
            return Components;
        }