// Set image to display by the control
        public int SetImage(Bitmap image)
        {
            leftEdges.Clear();
            rightEdges.Clear();
            topEdges.Clear();
            bottomEdges.Clear();
            hulls.Clear();
            quadrilaterals.Clear();

            selectedBlobID = 0;

            this.image = Accord.Imaging.Image.Clone(image, PixelFormat.Format24bppRgb);
            imageWidth = this.image.Width;
            imageHeight = this.image.Height;

            blobCounter.ProcessImage(this.image);
            blobs = blobCounter.GetObjectsInformation();

            GrahamConvexHull grahamScan = new GrahamConvexHull();

            foreach (Blob blob in blobs)
            {
                List<IntPoint> leftEdge = new List<IntPoint>();
                List<IntPoint> rightEdge = new List<IntPoint>();
                List<IntPoint> topEdge = new List<IntPoint>();
                List<IntPoint> bottomEdge = new List<IntPoint>();

                // collect edge points
                blobCounter.GetBlobsLeftAndRightEdges(blob, out leftEdge, out rightEdge);
                blobCounter.GetBlobsTopAndBottomEdges(blob, out topEdge, out bottomEdge);

                leftEdges.Add(blob.ID, leftEdge);
                rightEdges.Add(blob.ID, rightEdge);
                topEdges.Add(blob.ID, topEdge);
                bottomEdges.Add(blob.ID, bottomEdge);

                // find convex hull
                List<IntPoint> edgePoints = new List<IntPoint>();
                edgePoints.AddRange(leftEdge);
                edgePoints.AddRange(rightEdge);

                List<IntPoint> hull = grahamScan.FindHull(edgePoints);
                hulls.Add(blob.ID, hull);

                List<IntPoint> quadrilateral = null;

                // find quadrilateral
                if (hull.Count < 4)
                {
                    quadrilateral = new List<IntPoint>(hull);
                }
                else
                {
                    quadrilateral = PointsCloud.FindQuadrilateralCorners(hull);
                }
                quadrilaterals.Add(blob.ID, quadrilateral);

                // shift all points for vizualization
                IntPoint shift = new IntPoint(1, 1);

                PointsCloud.Shift(leftEdge, shift);
                PointsCloud.Shift(rightEdge, shift);
                PointsCloud.Shift(topEdge, shift);
                PointsCloud.Shift(bottomEdge, shift);
                PointsCloud.Shift(hull, shift);
                PointsCloud.Shift(quadrilateral, shift);
            }

            UpdatePosition();
            Invalidate();

            return blobs.Length;
        }
        /// <summary>
        /// calculate the blob's position based on the grids position
        /// </summary>
        /// <param name="b"></param>
        /// <param name="offset"></param>
        private bool ProcessBlobs(BlobCounter bc)
        {
            var blobs = new List <Blob>(bc.GetObjectsInformation());

            blobs.RemoveAll(x => !Grid.Contains(x.CenterOfGravity));
            blobs.RemoveAll(x => x.Fullness < 0.5);
            //if (blobs.Count < 4)
            //{
            //    Debug.WriteLine("too few blobs");
            //    return false;
            //}
            //if (blobs.Count > 5)
            //{
            //    Debug.WriteLine("too many blobs");
            //    return false;
            //}
            var   refs    = new Dictionary <AForge.Point, Point>();
            var   parts   = (int)Math.Pow(2, _calibrationStep - 2);
            var   w       = _vs.Width / parts;
            var   h       = _vs.Height / parts;
            Point?missing = null;

            for (int i = 0; i <= parts; i++)
            {
                for (int j = 0; j <= parts; j++)
                {
                    if (i % 2 == 1)
                    {
                        if (j % 2 == 1)
                        {
                            //center of a rectangle
                            var tl = Grid.GetRefPoint((i - 1) * w, (j - 1) * h, 1);
                            var tr = Grid.GetRefPoint((i + 1) * w, (j - 1) * h, 1);
                            var bl = Grid.GetRefPoint((i - 1) * w, (j + 1) * h, 1);
                            var br = Grid.GetRefPoint((i + 1) * w, (j + 1) * h, 1);
                            refs.Add(new AForge.Point((tl.X + tr.X + bl.X + br.X) / 4.0f, (tl.Y + tr.Y + bl.Y + br.Y) / 4.0f), new Point(i, j));
                        }
                        else
                        {
                            // middle of a horizontal outline
                            var l = Grid.GetRefPoint((i - 1) * w, (j) * h, 1);
                            var r = Grid.GetRefPoint((i + 1) * w, (j) * h, 1);
                            refs.Add(new AForge.Point((l.X + r.X) / 2.0f, (l.Y + r.Y) / 2.0f), new Point(i, j));
                        }
                    }
                    else if (j % 2 == 1)
                    {
                        // middle of a horizontal outline
                        var t = Grid.GetRefPoint((i) * w, (j - 1) * h, 1);
                        var b = Grid.GetRefPoint((i) * w, (j + 1) * h, 1);
                        refs.Add(new AForge.Point((t.X + b.X) / 2.0f, (t.Y + b.Y) / 2.0f), new Point(i, j));
                    }
                }
            }
            var clusters = KMeansCluster.KMeansClustering(blobs.Select(x => x.CenterOfGravity).ToList(),
                                                          refs.Keys.ToList(), 5);

            foreach (var cluster in clusters)
            {
                if (cluster.Points.Count(refs.ContainsKey) > 1)
                {
                    Debug.WriteLine("Multiple Centers in a Cluster");
                    return(false);
                }
                if (!cluster.Points.Any(refs.ContainsKey))
                {
                    Debug.WriteLine("No Center in a Cluster");
                    return(false);
                }
                var center = cluster.Points.First(refs.ContainsKey);
                var pos    = refs[center];
                if (cluster.Points.Count == 1)
                {
                    Debug.WriteLine("Point missing in cluster");
                    if (missing.HasValue)
                    {
                        return(false);
                    }
                    missing = pos;
                    continue;
                }
                if (cluster.Points.Count > 2)
                {
                    Debug.WriteLine("Multiple Points in a cluster");
                }
                cluster.Points.Remove(center);
#if DEBUG
                foreach (var point in cluster.Points)
                {
                    using (var g = Graphics.FromImage(actImg))
                    {
                        g.DrawString(pos.X + "," + pos.Y, new Font(FontFamily.GenericSansSerif, 8.0f),
                                     new SolidBrush(Color.Red),
                                     point.X, point.Y);
                        g.Flush();
                        //Debug.WriteLine("wrote to image");
                    }
                }
#endif
                var p = cluster.Points.First();
                if (pos.X == 0)
                {
                    //left
                    var             b = blobs.First(x => x.CenterOfGravity == p);
                    List <IntPoint> rightEdge;
                    List <IntPoint> leftEdge;
                    bc.GetBlobsLeftAndRightEdges(b, out leftEdge, out rightEdge);
                    //var ep = leftEdge.First(x => x.Y == (int)Math.Round(p.Y));
                    //p = ep;
                    //p.Y = (float) Math.Round(leftEdge.Average(x => x.Y));
                    p = leftEdge.First(x => x.Y == (int)Math.Round(leftEdge.Average(y => y.Y)));
                }
                else if (pos.X == parts)
                {
                    //right
                    var             b = blobs.First(x => x.CenterOfGravity == p);
                    List <IntPoint> rightEdge;
                    List <IntPoint> leftEdge;
                    bc.GetBlobsLeftAndRightEdges(b, out leftEdge, out rightEdge);
                    //var ep = rightEdge.First(x => x.Y == (int)Math.Round(p.Y));
                    //p.X = ep.X;
                    p = rightEdge.First(x => x.Y == (int)Math.Round(rightEdge.Average(y => y.Y)));
                }
                if (pos.Y == 0)
                {
                    //top
                    var             b = blobs.First(x => x.CenterOfGravity == p);
                    List <IntPoint> bottomEdge;
                    List <IntPoint> topEdge;
                    bc.GetBlobsTopAndBottomEdges(b, out topEdge, out bottomEdge);
                    //var ep = topEdge.First(x => x.X == (int)Math.Round(p.X));
                    //p = ep;
                    //p.X = (float) topEdge.Average(x => x.X);
                    p = topEdge.First(x => x.X == (int)Math.Round(topEdge.Average(y => y.X)));
                }
                else if (pos.Y == parts)
                {
                    //bottom
                    var             b = blobs.First(x => x.CenterOfGravity == p);
                    List <IntPoint> bottomEdge;
                    List <IntPoint> topEdge;
                    bc.GetBlobsTopAndBottomEdges(b, out topEdge, out bottomEdge);
                    //var ep = bottomEdge.First(x => x.X == (int)Math.Round(p.X));
                    //p.Y = ep.Y;
                    p = bottomEdge.First(x => x.X == (int)Math.Round(bottomEdge.Average(y => y.X)));
                }
                var ip = p.Round();
                Grid.AddPoint(pos.X * w, pos.Y * h, ip.X, ip.Y);
            }
            return(true);
        }
        public int SetImage(Bitmap image)
        {
            leftEdges.Clear();
            rightEdges.Clear();
            topEdges.Clear();
            bottomEdges.Clear();
            hulls.Clear();
            quadrilaterals.Clear();

            selectedBlobID = 0;

            Bitmap imageclone = AForge.Imaging.Image.Clone(image, image.PixelFormat);
            // create filter
            Median filterMedian = new Median();
            // apply the filter
            // create filter
            Threshold filterThreshold = new Threshold(250);
            // configure filter
            // create filter
            BlobsFiltering filterBlobsFiltering = new BlobsFiltering();

            filterBlobsFiltering.CoupledSizeFiltering = false;
            filterBlobsFiltering.MinWidth             = 6; //7
            filterBlobsFiltering.MinHeight            = 6; //7
            filterBlobsFiltering.MaxWidth             = 8; //8
            filterBlobsFiltering.MaxHeight            = 8; //8
            // apply the filter
            filterThreshold.ApplyInPlace(imageclone);
            filterBlobsFiltering.ApplyInPlace(imageclone);
            filterMedian.ApplyInPlace(imageclone);

            //this.image  = AForge.Imaging.Image.Clone( image, PixelFormat.Format16bppGrayScale );
            //imageclone = AForge.Imaging.Image.Clone(image);
            imageWidth  = imageclone.Width;
            imageHeight = imageclone.Height;

            blobCounter.ProcessImage(imageclone);
            blobs  = blobCounter.GetObjectsInformation();
            center = new List <AForge.Point>();
            GrahamConvexHull grahamScan = new GrahamConvexHull();

            foreach (Blob blob in blobs)
            {
                List <IntPoint> leftEdge   = new List <IntPoint>();
                List <IntPoint> rightEdge  = new List <IntPoint>();
                List <IntPoint> topEdge    = new List <IntPoint>();
                List <IntPoint> bottomEdge = new List <IntPoint>();

                // collect edge points
                blobCounter.GetBlobsLeftAndRightEdges(blob, out leftEdge, out rightEdge);
                blobCounter.GetBlobsTopAndBottomEdges(blob, out topEdge, out bottomEdge);
                AForge.Point centering = blob.CenterOfGravity;
                leftEdges.Add(blob.ID, leftEdge);
                rightEdges.Add(blob.ID, rightEdge);
                topEdges.Add(blob.ID, topEdge);
                bottomEdges.Add(blob.ID, bottomEdge);

                // find convex hull
                List <IntPoint> edgePoints = new List <IntPoint>();
                edgePoints.AddRange(leftEdge);
                edgePoints.AddRange(rightEdge);

                List <IntPoint> hull = grahamScan.FindHull(edgePoints);
                hulls.Add(blob.ID, hull);

                List <IntPoint> quadrilateral = null;

                // List array center of gravity
                center.Add(centering);

                // find quadrilateral  //
                if (hull.Count < 4)
                {
                    quadrilateral = new List <IntPoint>(hull);
                }
                else
                {
                    quadrilateral = PointsCloud.FindQuadrilateralCorners(hull);
                }
                quadrilaterals.Add(blob.ID, quadrilateral);

                // shift all points for vizualization
                IntPoint shift = new IntPoint(1, 1);

                PointsCloud.Shift(leftEdge, shift);
                PointsCloud.Shift(rightEdge, shift);
                PointsCloud.Shift(topEdge, shift);
                PointsCloud.Shift(bottomEdge, shift);
                PointsCloud.Shift(hull, shift);
                PointsCloud.Shift(quadrilateral, shift);
            }

            double xhair = imageWidth / 2;
            double yhair = imageHeight / 2;

            if (image.PixelFormat != PixelFormat.Format24bppRgb)
            {
                //filterBlobX(516.0, 670.0);
                //filterBlobY(360.0, 520.0);

                filterBlobX(516.0, 1117.0);
                filterBlobY(357.0, 460.0);
                refPointList = new List <AForge.Point>();
                //findRef(388.0, 0.5);
                findRef(20.0, 1.5);//
                findPick(refPoint.X, refPoint.Y);
            }
            //UpdatePosition();
            //Invalidate();
            //if (!Directory.Exists(path))
            //{
            //    System.IO.Directory.CreateDirectory(path);
            //}

            ////file = path + DateTime.Now.ToString(datePatt);

            file = path + "visimg.bmp";
            imageclone.Save(file);
            if (blobs.Length > 0)
            {
                return(blobs.Length);
            }
            else
            {
                return(0);
            }
        }
Beispiel #4
0
        public double[] detectionGlyph(bool CalculTailleTerrain)
        {
            bool Trouve = false;

            double[] ratio = new double[2] {
                0, 0
            };
            SimpleShapeChecker shapeChecker = new SimpleShapeChecker();
            BlobCounter        blobCounter  = new BlobCounter();

            blobCounter.MinHeight    = 23;
            blobCounter.MinWidth     = 23;
            blobCounter.FilterBlobs  = true;
            blobCounter.ObjectsOrder = ObjectsOrder.Size;

            // 4 - find all stand alone blobs
            blobCounter.ProcessImage(imgContour);
            Blob[] blobs = blobCounter.GetObjectsInformation();

            // 5 - check each blob
            for (int i = 0, n = blobs.Length; i < n; i++)
            {
                List <IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blobs[i]);
                List <IntPoint> corners    = null;

                // Test de la forme selectionnée
                if (shapeChecker.IsQuadrilateral(edgePoints, out corners))
                {
                    // Détection des points de coutour
                    List <IntPoint> leftEdgePoints, rightEdgePoints, topEdgePoints, bottomEdgePoints;

                    Line Horizontale = Line.FromPoints(new IntPoint(0, 0), new IntPoint(10, 0));
                    blobCounter.GetBlobsLeftAndRightEdges(blobs[i], out leftEdgePoints, out rightEdgePoints);
                    blobCounter.GetBlobsTopAndBottomEdges(blobs[i], out topEdgePoints, out bottomEdgePoints);

                    // calculate average difference between pixel values from outside of the
                    // shape and from inside
                    float diff = CalculateAverageEdgesBrightnessDifference(leftEdgePoints, rightEdgePoints, imgNB);
                    // check average difference, which tells how much outside is lighter than
                    // inside on the average
                    if (diff > 20)
                    {
                        // Transformation de l'image reçu en un carré pour la reconnaissance
                        QuadrilateralTransformation quadrilateralTransformation = new QuadrilateralTransformation(corners, 60, 60);
                        UnmanagedImage glyphImage = quadrilateralTransformation.Apply(imgNB);

                        // Filtre de contraste
                        OtsuThreshold otsuThresholdFilter = new OtsuThreshold();
                        otsuThresholdFilter.ApplyInPlace(glyphImage);
                        imgContour = glyphImage;
                        // Reconnaissance du Glyph
                        Glyph Gl = new Glyph(glyphImage, GlyphSize);

                        Gl.ReconnaissanceGlyph(corners, imgNB);

                        // Si le Glyph est valide
                        if (Gl.getIdentifiant() > 0)
                        {
                            if (AutAffichage[0])
                            {
                                // Coloration des contours des zones détectées
                                UnImgReel.SetPixels(leftEdgePoints, Color.Red);
                                UnImgReel.SetPixels(rightEdgePoints, Color.Red);
                                UnImgReel.SetPixels(topEdgePoints, Color.Red);
                                UnImgReel.SetPixels(bottomEdgePoints, Color.Red);
                            }

                            // Détection du milieu
                            Line     line         = Line.FromPoints(corners[0], corners[2]);
                            Line     line2        = Line.FromPoints(corners[1], corners[3]);
                            IntPoint intersection = (IntPoint)line.GetIntersectionWith(line2);
                            if (AutAffichage[1])
                            {
                                dessinePoint(intersection, UnImgReel, 4, Color.Yellow);
                            }

                            // Calcul de la rotation
                            Line   ComparasionAngle = Line.FromPoints(corners[0], corners[1]);
                            Double rotation         = (int)ComparasionAngle.GetAngleBetweenLines(Horizontale);
                            rotation   += 90 * Gl.getNbRotation();
                            Gl.rotation = 360 - rotation;
                            rotation   *= (Math.PI / 180.0);


                            // Calcul d'un point en bout de pince
                            float Taille = corners[0].DistanceTo(corners[1]);

                            float taille = (Taille / BibliotequeGlyph.Biblioteque[Gl.getPosition()].taille) * BibliotequeGlyph.Biblioteque[Gl.getPosition()].DistancePince;
                            int   x      = -(int)(System.Math.Sin(rotation) * taille);
                            int   y      = -(int)(System.Math.Cos(rotation) * taille);
                            x          += (int)intersection.X;
                            y          += (int)intersection.Y;
                            Gl.Position = new int[2] {
                                x, y
                            };
                            if (AutAffichage[2])
                            {
                                dessinePoint(new IntPoint(x, y), UnImgReel, 4, Color.Cyan);
                            }
                            imgContour = Gl.getImage();
                            addGlyph(Gl);

                            if (CalculTailleTerrain == true && Trouve == false)
                            {
                                Trouve = true;
                                int tailleglyph = BibliotequeGlyph.Biblioteque[Gl.getPosition()].taille;

                                // Pythagore pour detection taille
                                Rectangle       a     = blobs[i].Rectangle;
                                double          angle = -Gl.rotation + 180;
                                List <IntPoint> coins = new List <IntPoint>();
                                coins.Add(new IntPoint(100, 100));
                                coins.Add(new IntPoint(100, 100 + tailleglyph));
                                coins.Add(new IntPoint(100 + tailleglyph, 100 + tailleglyph));
                                coins.Add(new IntPoint(100 + tailleglyph, 100));
                                IntPoint Centre = new IntPoint((coins[2].X + coins[0].X) / 2, (coins[2].Y + coins[0].Y) / 2);
                                int      radius = (int)(0.5 * Math.Sqrt(coins[0].DistanceTo(coins[1]) * coins[0].DistanceTo(coins[1]) + coins[1].DistanceTo(coins[2]) * coins[1].DistanceTo(coins[2])));
                                double   alpha  = Math.Atan2(coins[0].DistanceTo(coins[1]), coins[1].DistanceTo(coins[2])) * (180 / Math.PI);

                                double ang = 0;
                                for (i = 0; i < 4; i++)
                                {
                                    IntPoint tmp = coins[i];
                                    switch (i)
                                    {
                                    case 0:
                                        ang = alpha - 180 + angle;
                                        break;

                                    case 1:
                                        ang = +angle - alpha;
                                        break;

                                    case 2:
                                        ang = +angle + alpha;
                                        break;

                                    case 3:
                                        ang = -alpha + 180 + angle;
                                        break;
                                    }
                                    ang  *= (Math.PI / 180);
                                    tmp.X = (int)(Centre.X + radius * Math.Cos(ang));
                                    tmp.Y = (int)(Centre.Y + radius * Math.Sin(ang));

                                    coins[i] = tmp;
                                }

                                Rectangle r = new Rectangle(min(coins[0].X, coins[1].X, coins[2].X, coins[3].X), min(coins[0].Y, coins[1].Y, coins[2].Y, coins[3].Y),
                                                            max(coins[0].X, coins[1].X, coins[2].X, coins[3].X) - min(coins[0].X, coins[1].X, coins[2].X, coins[3].X),
                                                            max(coins[0].Y, coins[1].Y, coins[2].Y, coins[3].Y) - min(coins[0].Y, coins[1].Y, coins[2].Y, coins[3].Y));
                                ratio[0] = ((double)r.Width / (double)a.Width) * 1.48;
                                ratio[1] = ((double)r.Height / (double)a.Height) * 1.48;
                            }
                        }
                    }
                }
            }
            if (Trouve == false || ratio[0] == 0 || ratio[0] == 1 || ratio[1] == 0 || ratio[1] == 1)
            {
                return(null);
            }
            ratio[0] *= 0.7;
            ratio[1] *= 0.7;
            return(ratio);
        }