Example #1
0
        /// <summary>
        /// Merges line segment blobs (connected components) in one LineDetection.
        /// </summary>
        /// <param name="segment">Detected blobs.</param>
        /// <param name="Input">Input image.</param>
        /// <param name="OX">Delta between the data array and actual position, X component.</param>
        /// <param name="OY">Delta between the data array and actual position, Y component.</param>
        /// <returns>A LineDetection from the blobs.</returns>
        static LineDetection MergeBlobs(DetectionSegment segment, double[,] Input, int OX, int OY)
        {
            double          Xmean = 0, Ymean = 0;
            double          XX = 0, XY = 0, YY = 0;
            double          Flux = 0;
            double          XBmean = 0, YBmean = 0;
            List <double>   PValues      = new List <double>();
            List <IntPoint> MergedPoints = segment.Blobs.Aggregate(new List <IntPoint>(), (x, y) => { x.AddRange(y.Points); return(x); });

            foreach (IntPoint pt in MergedPoints)
            {
                double Val = Input[pt.Y, pt.X];
                Xmean  += pt.X; Ymean += pt.Y;
                XBmean += Val * pt.X; YBmean += Val * pt.Y;
                XX     += pt.X * pt.X; XY += pt.X * pt.Y; YY += pt.Y * pt.Y;
                Flux   += Val;
                PValues.Add(Val);
            }
            Xmean  /= MergedPoints.Count;
            Ymean  /= MergedPoints.Count;
            XBmean /= Flux;
            YBmean /= Flux;
            XX     /= MergedPoints.Count;
            XY     /= MergedPoints.Count;
            YY     /= MergedPoints.Count;
            XX     -= Xmean * Xmean;
            XY     -= Xmean * Ymean;
            YY     -= Ymean * Ymean;

            double Msq = Sqrt(XX * XX + 4 * XY * XY - 2 * XX * YY + YY * YY);
            double L1  = 1.0 / 2 * (XX + YY - Msq);
            double L2  = 1.0 / 2 * (XX + YY + Msq);
            double A1  = Atan2(2 * XY, -(-XX + YY + Msq));
            double A2  = Atan2(2 * XY, -(-XX + YY - Msq));

            LineDetection ld = new LineDetection()
            {
                Points = MergedPoints.Select((x) => new PixelPoint()
                {
                    X = x.X + OX, Y = x.Y + OY
                }).ToList(),
                EigenValue1 = L1,
                EigenValue2 = L2,
                EigenAngle1 = A1,
                EigenAngle2 = A2,
                Barycenter  = new PixelPoint()
                {
                    X = XBmean + OX, Y = YBmean + OY
                },
                PointsCenter = new PixelPoint()
                {
                    X = Xmean + OX, Y = Ymean + OY
                },
                Flux        = Flux,
                PointValues = PValues
            };

            return(ld);
        }
Example #2
0
        /// <summary>
        /// Scans a line on the image for line segments using a hysteresis connected component algorithm.
        /// </summary>
        /// <param name="Input">Input data.</param>
        /// <param name="AnalyzeMask">Mask for marking visited pixels.</param>
        /// <param name="Height">Data height.</param>
        /// <param name="Width">Data width.</param>
        /// <param name="Rho">Distance from origin to line.</param>
        /// <param name="Theta">Line angle.</param>
        /// <param name="HighTh">Upper hysteresis threshold.</param>
        /// <param name="LowTh">Lower hysteresis threshold.</param>
        /// <param name="MaxIgnore">Maximum interblob distance.</param>
        /// <param name="ScanWidth">Width of the scanned area.</param>
        /// <param name="OX">Image data origin X coordinate.</param>
        /// <param name="OY">Image data origin Y coordinate.</param>
        /// <returns>A list of line segment detections.</returns>
        internal static List <LineDetection> AnalyzeLine(double[,] Input, bool[,] AnalyzeMask, int Height, int Width, double Rho, double Theta, double HighTh, double LowTh, int MaxIgnore, int ScanWidth, int OX, int OY)
        {
            /* Unit vector in the direction of the line */
            Vector LineVector = new Vector()
            {
                X = Cos(Theta), Y = Sin(Theta)
            };
            /* Origin of the line */
            Vector LineOrigin = new Vector()
            {
                X = -Rho *Sin(Theta), Y = Rho * Cos(Theta)
            };
            /* Unit vector perpendicular to the line */
            Vector LONormal = new Vector()
            {
                X = -Sin(Theta), Y = Cos(Theta)
            };

            /* Compute the intersections with the bounding box */
            Vector LeftIntersect;
            double LDist;

            if (!LineIntersection.IntersectLeft(LineOrigin, LineVector, Width, Height, out LeftIntersect, out LDist))
            {
                return(null);
            }

            Vector RightIntersect;
            double RDist;

            if (!LineIntersection.IntersectRight(LineOrigin, LineVector, Width, Height, out RightIntersect, out RDist))
            {
                return(null);
            }

            /* Sort the intersections */
            double Start = Min(LDist, RDist);
            double End = Max(LDist, RDist);
            Vector StVec, EVec;

            if (Start == LDist && End == RDist)
            {
                StVec = LeftIntersect; EVec = RightIntersect;
            }
            else if (Start == RDist && End == LDist)
            {
                StVec = RightIntersect; EVec = LeftIntersect;
            }
            else
            {
                throw new ApplicationException("Geometry error.");
            }

            /* Scan line for blobs */
            int    k;
            int    N  = (int)(End - Start);
            Vector pt = StVec;

            List <Vector>        LineIntervals = new List <Vector>();
            List <DetectionBlob> Blobs         = new List <DetectionBlob>();

            for (k = 0; k < N; k++, pt.Increment(LineVector))
            {
                int    l;
                Vector vl = pt;
                for (l = -ScanWidth; l < ScanWidth; l++, vl.Increment(LONormal))
                {
                    int X = (int)Round(vl.X);
                    int Y = (int)Round(vl.Y);
                    if (X < 0 || X >= Width)
                    {
                        continue;
                    }
                    if (Y < 0 || Y >= Height)
                    {
                        continue;
                    }
                    if (AnalyzeMask[Y, X])
                    {
                        continue;
                    }
                    double Val = Input[Y, X];

                    if (Val > HighTh)
                    {
                        DetectionBlob db = BitmapFill(Input, new IntPoint()
                        {
                            X = X, Y = Y
                        }, AnalyzeMask, LowTh, Theta);
                        LineIntervals.Add(new Vector()
                        {
                            X = db.LineStart, Y = db.LineEnd
                        });
                        Blobs.Add(db);
                    }
                }
            }

            /* Merge blobs into line segments */
            List <DetectionSegment> FoundSegments = new List <DetectionSegment>();
            DetectionSegment        cseg          = default(DetectionSegment); /* Current segment */

            for (k = 0; k < LineIntervals.Count; k++)
            {
                if (cseg.Blobs != null)
                {
                    /* If still within threshold of current segment */
                    if (Min(LineIntervals[k].X, LineIntervals[k].Y) < cseg.End + MaxIgnore)
                    {
                        cseg.Blobs.Add(Blobs[k]);
                        cseg.End = Max(cseg.End, Max(LineIntervals[k].Y, LineIntervals[k].X));
                        continue;
                    }
                    else
                    {
                        FoundSegments.Add(cseg); cseg = default(DetectionSegment);
                    }
                }
                /* Create new current segment */
                cseg.Blobs = new List <DetectionBlob>();
                cseg.Angle = Theta;
                cseg.Blobs.Add(Blobs[k]);
                cseg.Start = Min(LineIntervals[k].X, LineIntervals[k].Y);
                cseg.End   = Max(LineIntervals[k].Y, LineIntervals[k].X);
            }
            if (cseg.Blobs != null)
            {
                FoundSegments.Add(cseg);
            }
            List <LineDetection> Detections = FoundSegments.Select((x) => MergeBlobs(x, Input, OX, OY)).ToList();

            return(Detections);
        }