Beispiel #1
0
        public static void Run(Options options)
        {
            //load the image and compute the ratio of the old height
            //to the new height, clone it, and resize it
            using (var disposer = new Disposer())
            {
                var image = new Image <Bgr, byte>(options.Image);
                disposer.Add(image);
                Image <Bgr, byte> orig = image.Clone();
                disposer.Add(orig);
                double ratio = image.Height / 500.0;
                image = ImageUtil.Resize(image, height: 500);
                disposer.Add(image);

                Image <Gray, byte> gray = image.Convert <Gray, byte>();
                disposer.Add(gray);

                gray = gray.SmoothGaussian(5);
                disposer.Add(gray);

                Image <Gray, byte> edged = gray.Canny(75, 200);
                disposer.Add(edged);

                Console.WriteLine("STEP 1: Edge Detection");

                CvInvoke.Imshow("Image", image);
                CvInvoke.Imshow("Edged", edged);
                CvInvoke.WaitKey();
                CvInvoke.DestroyAllWindows();

                //find the contours in the edged image, keeping only the
                //largest ones, and initialize the screen contour
                VectorOfVectorOfPoint cnts = new VectorOfVectorOfPoint();
                disposer.Add(cnts);

                using (Image <Gray, byte> edgedClone = edged.Clone())
                {
                    CvInvoke.FindContours(edgedClone, cnts, null, RetrType.List, ChainApproxMethod.ChainApproxSimple);
                }


                Point[] screenCnt = null;
                foreach (VectorOfPoint c in
                         Enumerable.Range(0, cnts.Size).Select(i => cnts[i]).OrderByDescending(c => CvInvoke.ContourArea(c)).Take(5))
                {
                    //approximate the contour
                    double peri = CvInvoke.ArcLength(c, true);
                    using (VectorOfPoint approx = new VectorOfPoint())
                    {
                        CvInvoke.ApproxPolyDP(c, approx, 0.02 * peri, true);
                        if (approx.Size == 4)
                        {
                            screenCnt = approx.ToArray();
                            break;
                        }
                    }
                }
                if (screenCnt == null)
                {
                    Console.WriteLine("Failed to find polygon with four points");
                    return;
                }

                //show the contour (outline) of the piece of paper
                Console.WriteLine("STEP 2: Find contours of paper");
                image.Draw(screenCnt, new Bgr(0, 255, 0), 2);
                CvInvoke.Imshow("Outline", image);
                CvInvoke.WaitKey();
                CvInvoke.DestroyAllWindows();

                //apply the four point transform to obtain a top-down
                //view of the original image
                Image <Bgr, byte> warped = FourPointTransform(orig, screenCnt.Select(pt => new PointF((int)(pt.X * ratio), (int)(pt.Y * ratio))));
                disposer.Add(warped);

                //convert the warped image to grayscale, then threshold it
                //to give it that 'black and white' paper effect
                Image <Gray, byte> warpedGray = warped.Convert <Gray, byte>();
                disposer.Add(warpedGray);

                warpedGray = warpedGray.ThresholdAdaptive(new Gray(251), AdaptiveThresholdType.GaussianC, ThresholdType.Binary, 251, new Gray(10));
                disposer.Add(warpedGray);

                Console.WriteLine("STEP 3: Apply perspective transform");
                Image <Bgr, byte> origResized = ImageUtil.Resize(orig, height: 650);
                disposer.Add(origResized);
                CvInvoke.Imshow("Original", origResized);
                Image <Gray, byte> warpedResized = ImageUtil.Resize(warpedGray, height: 650);
                disposer.Add(warpedResized);
                CvInvoke.Imshow("Scanned", warpedResized);
                CvInvoke.WaitKey();
                CvInvoke.DestroyAllWindows();
            }
        }
Beispiel #2
0
        public Form1()
        {
            InitializeComponent();

            //Mat picture = new Mat(@"C:\Users\flore\Desktop\OK.png", Emgu.CV.CvEnum.LoadImageType.AnyColor); // Pick some path on your disk!
            //CvInvoke.Imshow("Hello World!", picture); // Open window with image


            Capture capture = new Capture(); //create a camera captue

            // var inImage = new Image<Bgr, byte>(@"PhotosCube\cube3.jpg");

            var processViewer = new ImageBox(); //create an image viewer

            this.pnl.Controls.Add(processViewer);
            processViewer.Dock   = DockStyle.Top;
            processViewer.Height = capture.Height;

            var cannyViewer = new ImageBox(); //create an image viewer

            this.pnl.Controls.Add(cannyViewer);
            cannyViewer.Dock   = DockStyle.Top;
            cannyViewer.Height = capture.Height;


            var contourViewer = new ImageBox(); //create an image viewer

            this.pnl.Controls.Add(contourViewer);
            contourViewer.Dock   = DockStyle.Top;
            contourViewer.Height = capture.Height;



            var viewer = new ImageBox(); //create an image viewer

            this.pnl.Controls.Add(viewer);
            viewer.Dock   = DockStyle.Top;
            viewer.Height = capture.Height;


            Vector2 vect1;
            Vector2 vect2;

            for (int i = 0; i < Colors.Count - 1; i++)
            {
                for (int j = i + 1; j < Colors.Count; j++)
                {
                    var dist = (Colors.Values.ElementAt(i) - Colors.Values.ElementAt(j)).LengthFast;

                    if (dist < MaxColorDistance)
                    {
                        MaxColorDistance = dist;
                        vect1            = Colors.Values.ElementAt(i);
                        vect2            = Colors.Values.ElementAt(j);
                    }
                }
            }


            Application.Idle += new EventHandler(delegate(object sender, EventArgs e)
            {
                //run this until application closed (close button click on image viewer)
                var frame   = capture.QueryFrame();
                var inImage = frame.ToImage <Bgr, byte>(); //draw the image obtained from camera

                var contourImage = inImage.Clone();

                //   Mat outImage = new Mat();

                //CvInvoke.MedianBlur(frame, outImage, 5);

                var processsImageChannels = new Image <Bgr, byte>(inImage.Size);
                CvInvoke.CvtColor(frame, processsImageChannels, ColorConversion.Rgb2Hsv);



                // var processsImage = new Mat();
                // CvInvoke.ExtractChannel(inImage, processsImage, 1);

                processViewer.Image = processsImageChannels;

                Mat canny = new Mat();

                CvInvoke.Canny(inImage, canny, barCanny1.Value, barCanny2.Value, 3, true);

                cannyViewer.Image = canny;

                //CvInvoke.DrawContours(outImage, contours,-1, new MCvScalar(0,0,255));

                using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
                {
                    CvInvoke.FindContours(canny, contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple);

                    var lstParallelogram = new List <Quadrilateral>();

                    for (int i = 0; i < contours.Size; i++)
                    {
                        using (VectorOfPoint contour = contours[i])
                            using (VectorOfPoint approxContour = new VectorOfPoint())
                            {
                                var arc = CvInvoke.ArcLength(contour, true);

                                // éliminer les objets les plus petits
                                if (arc / 4 < inImage.Width / 30)
                                {
                                    continue;
                                }

                                CvInvoke.ApproxPolyDP(contour, approxContour, arc * 0.1, true);

                                if (approxContour.Size == 4)
                                {
                                    var pts = approxContour.ToArray();

                                    contourImage.DrawPolyline(pts, true, new Bgr(Color.Green));

                                    var quadri = new Quadrilateral(pts, 0.1, 0.1);

                                    if (quadri.IsParallelogram)
                                    {
                                        lstParallelogram.Add(quadri);
                                    }
                                }
                            }
                    }

                    contourViewer.Image = contourImage;

                    // suppression des doublons
                    var comparer     = new QuadrilateralCenterComparer(0.3);
                    lstParallelogram = lstParallelogram.Distinct(comparer).ToList();

                    var lstSquares = lstParallelogram.Where((x) => x.IsSquare).ToList();

                    // nombre minimal de cube
                    if (lstSquares.Count > 5)
                    {
                        //var circle = CvInvoke.MinEnclosingCircle(lstCube.SelectMany((x) => x.Points).Select((x) => new PointF(x.X, x.Y)).ToArray());
                        //inImage.Draw(circle, new Bgr(255, 255, 0));

                        var minX = lstSquares.Min((x) => x.Center.X);
                        var maxX = lstSquares.Max((x) => x.Center.X);
                        var minY = lstSquares.Min((x) => x.Center.Y);
                        var maxY = lstSquares.Max((x) => x.Center.Y);



                        //inImage.Draw(new Rectangle((int)minX, (int)minY, (int)(maxX - minX), (int)(maxY - minY)), new Bgr(Color.Bisque), 1);

                        lstSquares.Min((x) => x.Center.X);

                        var averageLength  = lstSquares.Average((x) => x.AverageLength);
                        var centerDistance = averageLength * 1.4;

                        var bottom = new Vector2(lstSquares.Average((x) => x.Bottom.X), lstSquares.Average((x) => x.Bottom.Y));

                        bottom.Normalize();

                        var right = new Vector2(bottom.Y, -bottom.X);



                        var pastilles = new List <Pastille>();

                        var pastilleOrigine           = new Pastille();
                        pastilleOrigine.m             = 0;
                        pastilleOrigine.n             = 0;
                        pastilleOrigine.Quadrilateral = lstSquares[0];
                        pastilleOrigine.Center        = lstSquares[0].Center;
                        pastilles.Add(pastilleOrigine);

                        var origine = lstSquares[0].Center;

                        for (int i = 1; i < lstSquares.Count; i++)
                        {
                            var u = lstSquares[i].Center - origine;

                            var pastille           = new Pastille();
                            pastille.Quadrilateral = lstSquares[i];

                            //inImage.DrawPolyline(quadri.Points, true, new Bgr(Color.Blue), 3);
                            pastille.n = (int)Math.Round(Vector2.Dot(u, bottom) / centerDistance);
                            pastille.m = (int)Math.Round(Vector2.Dot(u, right) / centerDistance);

                            pastille.Center = lstSquares[i].Center;

                            pastilles.Add(pastille);
                        }

                        var xMax = pastilles.Max((x) => x.m);
                        var xMin = pastilles.Min((x) => x.m);
                        var yMax = pastilles.Max((x) => x.n);
                        var yMin = pastilles.Min((x) => x.n);

                        if (xMax - xMin != 3 || yMax - yMin != 3)
                        {
                            return;                                       // ce n'est pas un cube 4x4
                        }
                        // x et y entre 0 et 3
                        pastilles.ForEach((x) => { x.m -= xMin; x.n -= yMin; });

                        // recalcul de centerDistance
                        centerDistance = 0;
                        for (int i = 0; i < pastilles.Count - 1; i++)
                        {
                            var dm          = pastilles[i + 1].m - pastilles[i].m;
                            var dn          = pastilles[i + 1].n - pastilles[i].n;
                            centerDistance += (pastilles[i].Center - pastilles[i + 1].Center).LengthFast / Math.Sqrt(dm * dm + dn * dn);
                        }
                        centerDistance /= pastilles.Count - 1;

                        Pastille[,] pastilleMatrix = new Pastille[4, 4];


                        //http://www.wolframalpha.com/input/?i=x%3Dx1%2Bk1*u1,x%3Dx2%2Bk2*u2,y%3Dy1%2Bk1*v1,y%3Dy2%2Bk2*v2+for+x,y

                        for (int m = 0; m < 4; m++)
                        {
                            for (int n = 0; n < 4; n++)
                            {
                                var pastille = pastilles.FirstOrDefault((x) => x.m == m && x.n == n);

                                if (pastille == null)
                                {
                                    pastille   = new Pastille();
                                    pastille.m = m;
                                    pastille.n = n;

                                    // calcul de la position des pastilles non détéctées
                                    foreach (var p in pastilles)
                                    {
                                        pastille.Center += p.Center + (float)centerDistance * ((m - p.m) * right + (n - p.n) * bottom);
                                    }
                                    pastille.Center /= pastilles.Count;
                                }

                                pastilleMatrix[m, n] = pastille;

                                var ptRect = pastille.Center - new Vector2(averageLength / 4);

                                if (ptRect.X < 0)
                                {
                                    ptRect.X = 0;
                                }
                                else if (ptRect.X + averageLength / 2 >= inImage.Width)
                                {
                                    ptRect.X = inImage.Width - 1 - (int)averageLength / 2;
                                }

                                if (ptRect.Y < 0)
                                {
                                    ptRect.Y = 0;
                                }
                                else if (ptRect.Y + averageLength / 2 >= inImage.Height)
                                {
                                    ptRect.Y = inImage.Height - 1 - (int)averageLength / 2;
                                }

                                var rectangle = new Rectangle((int)ptRect.X, (int)ptRect.Y, (int)averageLength / 2, (int)averageLength / 2);
                                var rectMat   = processsImageChannels.GetSubRect(rectangle);

                                var color = CvInvoke.Mean(rectMat);

                                pastille.MeanColor.MCvScalar = color;

                                var minDist = float.MaxValue;
                                foreach (var elt in Colors)
                                {
                                    var dist = (elt.Value - new Vector2((float)color.V0, (float)color.V1)).Length;

                                    if (dist < minDist)
                                    {
                                        minDist        = dist;
                                        pastille.Color = elt.Key;
                                    }
                                }
                            }
                        }


                        //    inImage.Draw(pastille.X + ";" + pastille.Y, new Point((int)lstSquares[i].Center.X - 10, (int)lstSquares[i].Center.Y + 10), FontFace.HersheyComplex, 0.5, new Bgr(Color.Aquamarine), 1);

                        // int n = 0;

                        h.Add(pastilleMatrix[0, 0].MeanColor.Hue);
                        s.Add(pastilleMatrix[0, 0].MeanColor.Satuation);

                        lblH.Text = h.Average().ToString();
                        lblS.Text = s.Average().ToString();

                        foreach (var pastille in pastilleMatrix)
                        {
                            if (pastille.Quadrilateral != null)
                            {
                                inImage.DrawPolyline(pastille.Quadrilateral.Points, true, new Bgr(Color.Blue), 3);
                                inImage.Draw(new LineSegment2D(new Point((int)(pastille.Quadrilateral.Center.X), (int)(pastille.Quadrilateral.Center.Y)), new Point((int)(pastille.Quadrilateral.Center.X + right.X * 20), (int)(pastille.Quadrilateral.Center.Y + right.Y * 20))), new Bgr(Color.SeaGreen), 3);
                                inImage.Draw(new LineSegment2D(new Point((int)(pastille.Quadrilateral.Center.X), (int)(pastille.Quadrilateral.Center.Y)), new Point((int)(pastille.Quadrilateral.Center.X + bottom.X * 20), (int)(pastille.Quadrilateral.Center.Y + bottom.Y * 20))), new Bgr(Color.Red), 3);
                                inImage.Draw(pastille.m + ";" + pastille.n, new Point((int)pastille.Quadrilateral.Center.X - 10, (int)pastille.Quadrilateral.Center.Y + 10), FontFace.HersheyComplex, 0.5, new Bgr(Color.Aquamarine), 1);
                            }
                            else
                            {
                                var circle = new CircleF(new PointF(pastille.Center.X, pastille.Center.Y), averageLength / 4);
                                inImage.Draw(circle, new Bgr(Color.Pink), (int)averageLength / 4);
                                //inImage.Draw(circle, new Bgr(Color.Pink), 3);
                            }


                            var l    = 20;
                            var rect = new Rectangle(pastille.m * l + l, pastille.n * l + l, l / 2, l / 2);
                            inImage.Draw(rect, new Bgr(pastille.Color), l / 2, LineType.AntiAlias);



                            // n++;
                            //  inImage.Draw(n.ToString(), new Point(quadri.Points.Sum((x) => x.X) / 4 - 10, quadri.Points.Sum((x) => x.Y) / 4 + 10), FontFace.HersheyComplex, 0.5, new Bgr(Color.Aquamarine), 1);
                        }
                        inImage.Draw(new CircleF(new PointF(origine.X, origine.Y), 5), new Bgr(Color.Purple), 10);


                        //var angles = lstParallelogram.SelectMany((x) => x.Angles).ToList();


                        //angles.Sort();


                        //var derivateAngle = new List<double>(angles.Count-1);

                        //for (int a=0;a<angles.Count-1;a++)
                        //{
                        //    derivateAngle.Add(angles[a + 1] - angles[a]);
                        //}

                        //derivateAngle.Sort();

                        //lblNbFace.Text = derivateAngle.Count((x) => x > 0.5).ToString();
                    }
                    else
                    {
                        h.Clear();
                        s.Clear();
                    }
                }

                // CvInvoke.inra

                // CvInvoke.CvtColor(inImage, outImage, ColorConversion.Rgb2Hsv);

                //var hue = outImage.Split()[0];

                //CvInvoke.Laplacian(inImage, outImage, DepthType.Default, 3);

                // CvInvoke.Erode(inImage, outImage, null, new Point(-1, -1), 3, BorderType.Default, new MCvScalar(1));


                viewer.Image = inImage;
            });



            /*
             * Mat outImage = new Mat();
             *
             * CvInvoke.MedianBlur(inImage, outImage, 5);
             *
             * Mat canny = new Mat();
             *
             * CvInvoke.Canny(outImage, canny, barCanny1.Value, barCanny2.Value);
             *
             *
             * var contours = new VectorOfVectorOfPoint();
             * var hierarchy = new Mat();
             *
             * CvInvoke.FindContours(canny, contours, hierarchy, RetrType.List, ChainApproxMethod.ChainApproxNone);
             *
             *
             * CvInvoke.DrawContours(outImage, contours, -1, new MCvScalar(0, 0, 255), 1, LineType.FourConnected, hierarchy);
             *
             *
             * var area = new List<double>();
             *
             * for(int i=0;i<contours.Size;i++)
             * {
             *  var contour = contours[i];
             *
             *  area.Add( CvInvoke.ContourArea(contour));
             * }
             *
             * area.Sort();
             *
             * richTextBox1.Text = String.Join("\r\n", area.Select((x) => x.ToString()).ToArray());
             *
             *
             *
             * viewer.Image = outImage;
             */


            return;



            StringBuilder msgBuilder = new StringBuilder("Performance: ");

            //Load the image from file and resize it for display
            Image <Bgr, Byte> img =
                new Image <Bgr, byte>(@"PhotosCube\cube3.jpg");

            //Convert the image to grayscale and filter out the noise
            UMat uimage = new UMat();

            CvInvoke.CvtColor(img, uimage, ColorConversion.Bgr2Gray);

            //use image pyr to remove noise
            //  UMat pyrDown = new UMat();
            //CvInvoke.PyrDown(uimage, pyrDown);
            //CvInvoke.PyrUp(pyrDown, uimage);

            //Image<Gray, Byte> gray = img.Convert<Gray, Byte>().PyrDown().PyrUp();

            //#region circle detection
            Stopwatch watch          = Stopwatch.StartNew();
            double    cannyThreshold = 30;

            /*
             * double circleAccumulatorThreshold = 100;
             * CircleF[] circles = CvInvoke.HoughCircles(uimage, HoughType.Gradient, 2.0, 20.0, cannyThreshold, circleAccumulatorThreshold, 5);
             *
             * watch.Stop();
             * msgBuilder.Append(String.Format("Hough circles - {0} ms; ", watch.ElapsedMilliseconds));
             #endregion
             */
            #region Canny and edge detection
            watch.Reset(); watch.Start();
            double cannyThresholdLinking = 100;
            UMat   cannyEdges            = new UMat();
            CvInvoke.Canny(uimage, cannyEdges, cannyThreshold, cannyThresholdLinking);

            LineSegment2D[] lines = CvInvoke.HoughLinesP(
                cannyEdges,
                1,              //Distance resolution in pixel-related units
                Math.PI / 45.0, //Angle resolution measured in radians.
                20,             //threshold
                30,             //min Line width
                10);            //gap between lines

            watch.Stop();
            msgBuilder.Append(String.Format("Canny & Hough lines - {0} ms; ", watch.ElapsedMilliseconds));
            #endregion

            #region Find triangles and rectangles
            watch.Reset(); watch.Start();
            List <Triangle2DF> triangleList = new List <Triangle2DF>();
            List <RotatedRect> boxList      = new List <RotatedRect>(); //a box is a rotated rectangle

            using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
            {
                CvInvoke.FindContours(cannyEdges, contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple);

                CvInvoke.DrawContours(img, contours, -1, new MCvScalar(0, 0, 255));

                int count = contours.Size;
                for (int i = 0; i < count; i++)
                {
                    using (VectorOfPoint contour = contours[i])
                        using (VectorOfPoint approxContour = new VectorOfPoint())
                        {
                            CvInvoke.ApproxPolyDP(contour, approxContour, CvInvoke.ArcLength(contour, true) * 0.05, true);

                            var a = new VectorOfVectorOfPoint();



                            // img.Draw(approxContour, new Bgr(Color.DarkOrange), 2);


                            CvInvoke.DrawContours(img, approxContour, 0, new MCvScalar(0, 255, 0));

                            if (CvInvoke.ContourArea(approxContour, false) > 2) //only consider contours with area greater than 250
                            {
                                if (approxContour.Size == 3)                    //The contour has 3 vertices, it is a triangle
                                {
                                    Point[] pts = approxContour.ToArray();
                                    triangleList.Add(new Triangle2DF(
                                                         pts[0],
                                                         pts[1],
                                                         pts[2]
                                                         ));
                                }
                                else if (approxContour.Size == 4) //The contour has 4 vertices.
                                {
                                    /*
                                     #region determine if all the angles in the contour are within [80, 100] degree
                                     * bool isRectangle = true;
                                     * Point[] pts = approxContour.ToArray();
                                     * LineSegment2D[] edges = PointCollection.PolyLine(pts, true);
                                     *
                                     * for (int j = 0; j < edges.Length; j++)
                                     * {
                                     *  double angle = Math.Abs(
                                     *     edges[(j + 1) % edges.Length].GetExteriorAngleDegree(edges[j]));
                                     *  if (angle < 80 || angle > 100)
                                     *  {
                                     *      isRectangle = false;
                                     *      break;
                                     *  }
                                     * }
                                     #endregion
                                     *
                                     * if (isRectangle) */        // boxList.Add(CvInvoke.MinAreaRect(approxContour));
                                }
                            }
                        }
                }
            }

            watch.Stop();
            msgBuilder.Append(String.Format("Triangles & Rectangles - {0} ms; ", watch.ElapsedMilliseconds));
            #endregion

            this.Text = msgBuilder.ToString();

            #region draw triangles and rectangles
            //Image<Bgr, Byte> triangleRectangleImage = img.CopyBlank();
            //foreach (Triangle2DF triangle in triangleList)
            //img.Draw(triangle, new Bgr(Color.DarkBlue), 2);
            foreach (RotatedRect box in boxList)
            {
                img.Draw(box, new Bgr(Color.DarkOrange), 2);
            }
            #endregion

            /*
             #region draw circles
             * // Image<Bgr, Byte> circleImage = img.CopyBlank();
             * // foreach (CircleF circle in circles)
             * //    img.Draw(circle, new Bgr(Color.Brown), 2);
             #endregion
             *
             *
             #region draw lines
             * //Image<Bgr, Byte> lineImage = img.CopyBlank();
             * foreach (LineSegment2D line in lines)
             *  img.Draw(line, new Bgr(Color.Green), 2);
             #endregion
             */

            viewer.Image = img;
        }
Beispiel #3
0
        private void FindStopSign(Mat img, List <Mat> stopSignList, List <Rectangle> boxList, VectorOfVectorOfPoint contours, int[,] hierachy, int idx)
        {
            for (; idx >= 0; idx = hierachy[idx, 0])
            {
                using (VectorOfPoint c = contours[idx])
                    using (VectorOfPoint approx = new VectorOfPoint())
                    {
                        CvInvoke.ApproxPolyDP(c, approx, CvInvoke.ArcLength(c, true) * 0.02, true);
                        double area = CvInvoke.ContourArea(approx);
                        if (area > 200)
                        {
                            double ratio = CvInvoke.MatchShapes(_octagon, approx, Emgu.CV.CvEnum.ContoursMatchType.I3);

                            if (ratio > 0.1) //not a good match of contour shape
                            {
                                //check children
                                if (hierachy[idx, 2] >= 0)
                                {
                                    FindStopSign(img, stopSignList, boxList, contours, hierachy, hierachy[idx, 2]);
                                }
                                continue;
                            }

                            Rectangle box = CvInvoke.BoundingRectangle(c);

                            Mat candidate = new Mat();
                            using (Mat tmp = new Mat(img, box))
                                CvInvoke.CvtColor(tmp, candidate, ColorConversion.Bgr2Gray);

                            //set the value of pixels not in the contour region to zero
                            using (Mat mask = new Mat(candidate.Size.Height, candidate.Width, DepthType.Cv8U, 1))
                            {
                                mask.SetTo(new MCvScalar(0));
                                CvInvoke.DrawContours(mask, contours, idx, new MCvScalar(255), -1, LineType.EightConnected, null, int.MaxValue, new Point(-box.X, -box.Y));

                                double mean = CvInvoke.Mean(candidate, mask).V0;
                                CvInvoke.Threshold(candidate, candidate, mean, 255, ThresholdType.Binary);
                                CvInvoke.BitwiseNot(candidate, candidate);
                                CvInvoke.BitwiseNot(mask, mask);

                                candidate.SetTo(new MCvScalar(0), mask);
                            }

                            int              minMatchCount         = 8;
                            double           uniquenessThreshold   = 0.8;
                            VectorOfKeyPoint _observeredKeypoint   = new VectorOfKeyPoint();
                            Mat              _observeredDescriptor = new Mat();
                            _detector.DetectAndCompute(candidate, null, _observeredKeypoint, _observeredDescriptor, false);

                            if (_observeredKeypoint.Size >= minMatchCount)
                            {
                                int k = 2;

                                Mat mask;

                                using (VectorOfVectorOfDMatch matches = new VectorOfVectorOfDMatch())
                                {
                                    _modelDescriptorMatcher.KnnMatch(_observeredDescriptor, matches, k, null);
                                    mask = new Mat(matches.Size, 1, DepthType.Cv8U, 1);
                                    mask.SetTo(new MCvScalar(255));
                                    Features2DToolbox.VoteForUniqueness(matches, uniquenessThreshold, mask);
                                }

                                int nonZeroCount = CvInvoke.CountNonZero(mask);
                                if (nonZeroCount >= minMatchCount)
                                {
                                    boxList.Add(box);
                                    stopSignList.Add(candidate);
                                }
                            }
                        }
                    }
            }
        }
Beispiel #4
0
        void DetectPolygons(UMat cannyEdgesImg, bool detectTriangles, bool detectRectangles, bool detectHexagons, int area)
        {
            triangles  = new List <Triangle2DF>();
            rectangles = new List <RotatedRect>();
            hexagons   = new List <LineSegment2D[]>();

            //Find contours
            VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();

            CvInvoke.FindContours(cannyEdgesImg, contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple);

            //Check all contours
            for (int i = 0; i < contours.Size; i++)
            {
                VectorOfPoint contour = contours[i];

                //Approximate a polygon
                VectorOfPoint approxContour = new VectorOfPoint();
                CvInvoke.ApproxPolyDP(contour, approxContour, CvInvoke.ArcLength(contour, true) * 0.025, true);

                //Contours bigger than defined area
                if (CvInvoke.ContourArea(approxContour, false) > 250)
                {
                    int areaTresshold = 1000;
                    if (area != 0)
                    {
                        if (CvInvoke.ContourArea(approxContour, false) < area - areaTresshold ||
                            CvInvoke.ContourArea(approxContour, false) > area + areaTresshold)
                        {
                            //Consider contours near defined area
                            //If area is smaller or bigger than defined -> continue to next countour as this one doesn't fit
                            continue;
                        }
                    }

                    //Add triangle
                    if (approxContour.Size == 3 && detectTriangles)
                    {
                        Point[] pts = approxContour.ToArray();
                        triangles.Add(new Triangle2DF(pts[0], pts[1], pts[2]));
                    }
                    //Add rectangle
                    else if (approxContour.Size == 4 && detectRectangles)
                    {
                        //Determine if all angles in the contour are within [80, 100] degree
                        bool            isRectangle = true;
                        Point[]         pts         = approxContour.ToArray();
                        LineSegment2D[] edges       = PointCollection.PolyLine(pts, true);

                        for (int j = 0; j < edges.Length; j++)
                        {
                            double angle = Math.Abs(edges[(j + 1) % edges.Length].GetExteriorAngleDegree(edges[j]));
                            if (angle < 80 || angle > 100)
                            {
                                isRectangle = false;
                                break;
                            }
                        }

                        if (isRectangle)
                        {
                            rectangles.Add(CvInvoke.MinAreaRect(approxContour));
                        }
                    }
                    //Add hexagon
                    else if (approxContour.Size == 6 && detectHexagons)
                    {
                        // Determine if all the angles in the contour are within [50, 70] degree
                        bool            isHexagon = true;
                        Point[]         pts       = approxContour.ToArray();
                        LineSegment2D[] edges     = PointCollection.PolyLine(pts, true);

                        for (int j = 0; j < edges.Length; j++)
                        {
                            double angle = Math.Abs(edges[(j + 1) % edges.Length].GetExteriorAngleDegree(edges[j]));
                            if (angle < 50 || angle > 70)
                            {
                                isHexagon = false;
                                break;
                            }
                        }

                        if (isHexagon)
                        {
                            hexagons.Add(edges);
                        }
                    }
                }
            }
        }
Beispiel #5
0
        private static void FindRectangle(int min, int max)
        {
            Image <Rgb, Byte>  img       = new Image <Rgb, byte>(ori_img);
            Image <Gray, Byte> edgeImage = new Image <Gray, byte>(show_img);

            #region Find rectangles
            boxList = new List <RotatedRect>(); //a box is a rotated rectangle
            double rate = img.Width * img.Height / 3864714.0;
            bool   isIDPExist = false, isUseExist = false, isAddressExist = false;
            using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
            {
                CvInvoke.FindContours(edgeImage, contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple);
                int count = contours.Size;
                for (int i = 0; i < count; i++)
                {
                    using (VectorOfPoint contour = contours[i])
                        using (VectorOfPoint approxContour = new VectorOfPoint())
                        {
                            CvInvoke.ApproxPolyDP(contour, approxContour, CvInvoke.ArcLength(contour, true) * 0.05, true);
                            double area = CvInvoke.ContourArea(contour, false);
                            if (area > 100000 * rate && area < 142000 * rate && !isIDPExist)
                            {
                                // eid, date, price
                                Point[]  pts  = contour.ToArray();
                                PointF[] ptfs = new PointF[pts.Length];
                                for (int pi = 0; pi < pts.Length; pi++)
                                {
                                    ptfs[pi] = new PointF(pts[pi].X, pts[pi].Y);
                                }
                                Rectangle rec = PointCollection.BoundingRectangle(ptfs);
                                img.Draw(rec, new Rgb(Color.DarkOrange), 2);
                                rects.Add(rec);
                                isIDPExist = true;
                            }
                            else if (area > 350000 * rate && area < 450000 * rate)
                            {
                                // use
                                Point[]  pts = contour.ToArray();
                                PointF[] ptfs = new PointF[4];
                                int      minx = int.MaxValue, miny = int.MaxValue, maxx = 0, maxy = 0;
                                for (int pi = 0; pi < pts.Length; pi++)
                                {
                                    if (pts[pi].X < minx)
                                    {
                                        minx = pts[pi].X;
                                    }
                                    if (pts[pi].Y < miny)
                                    {
                                        miny = pts[pi].Y;
                                    }
                                    if (pts[pi].X > maxx)
                                    {
                                        maxx = pts[pi].X;
                                    }
                                    if (pts[pi].Y > maxy)
                                    {
                                        maxy = pts[pi].Y;
                                    }
                                }
                                ptfs[0] = new PointF(minx, miny);
                                ptfs[1] = new PointF(minx, (miny + maxy) / 2);
                                ptfs[2] = new PointF(maxx, miny);
                                ptfs[3] = new PointF(maxx, (miny + maxy) / 2);
                                Rectangle rec = PointCollection.BoundingRectangle(ptfs);
                                img.Draw(PointCollection.BoundingRectangle(ptfs), new Rgb(Color.DarkOrange), 2);
                                if (!isUseExist)
                                {
                                    rects.Add(rec);
                                    isUseExist = true;
                                }


                                PointF[] ptfks = new PointF[4];
                                ptfks[0] = new PointF(maxx * 1.5f, maxy);
                                ptfks[1] = new PointF(maxx * 1.5f, (float)(maxy + 32 * rate));
                                ptfks[2] = new PointF(minx, maxy);
                                ptfks[3] = new PointF(minx, (float)(maxy + 32 * rate));
                                Rectangle rec2 = PointCollection.BoundingRectangle(ptfks);
                                img.Draw(PointCollection.BoundingRectangle(ptfks), new Rgb(Color.DarkOrange), 2);
                                if (!isAddressExist)
                                {
                                    rects.Add(rec2);
                                    isAddressExist = true;
                                }
                            }
                            else if (area > min * rate && area < max * rate)
                            {
                                Point[]  pts  = contour.ToArray();
                                PointF[] ptfs = new PointF[pts.Length];
                                for (int pi = 0; pi < pts.Length; pi++)
                                {
                                    ptfs[pi] = new PointF(pts[pi].X, pts[pi].Y);
                                }
                                Rectangle rec = PointCollection.BoundingRectangle(ptfs);
                                img.Draw(rec, new Rgb(Color.DarkOrange), 2);
                                rects.Add(rec);
                            }
                        }
                }
            }
            #endregion
            #region draw rectangles

            foreach (RotatedRect box in boxList)
            {
                img.Draw(box, new Rgb(Color.DarkOrange), 2);
            }
            pre_img  = show_img;
            show_img = img.Bitmap;
            rform.UpdateImage(show_img);
            //img.Save("rect_" + this.count + ".png");
            #endregion
        }
Beispiel #6
0
        void DetectPolygons(UMat cannyEdgesImg, bool detectTriangles, bool detectRectangles, bool detectHexagons, int area)
        {
            triangles  = new List <Triangle2DF>();
            rectangles = new List <RotatedRect>();
            hexagons   = new List <LineSegment2D[]>();

            // find contours from binary image
            VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();

            CvInvoke.FindContours(cannyEdgesImg, contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple);

            for (int i = 0; i < contours.Size; i++)
            {                                        // go trough all detected contours
                VectorOfPoint contour = contours[i]; // select i-th contour

                // approximate a polygon
                VectorOfPoint approxContour = new VectorOfPoint();
                CvInvoke.ApproxPolyDP(contour, approxContour, CvInvoke.ArcLength(contour, true) * 0.025, true);

                if (CvInvoke.ContourArea(approxContour, false) > 250) //only consider contours bigger than defined area
                {
                    int areaTresshold = 1000;
                    if (area != 0)
                    {
                        if (CvInvoke.ContourArea(approxContour, false) < area - areaTresshold || CvInvoke.ContourArea(approxContour, false) > area + areaTresshold)
                        { //only consider contours near defined area
                          // if area is smaller or bigger than defined -> continue to next countour as this one doesn't fit
                            continue;
                        }

                        // debug - min area
                        //if (CvInvoke.ContourArea(approxContour, false) > area)
                        //    continue;
                    }


                    if (approxContour.Size == 3 && detectTriangles)
                    {                                                           // triangle
                        Point[] pts = approxContour.ToArray();                  // take points that define a triangle
                        triangles.Add(new Triangle2DF(pts[0], pts[1], pts[2])); // add triangle to the list
                    }
                    else if (approxContour.Size == 4 && detectRectangles)
                    { // rectangle
                        // Determine if all the angles in the contour are within [80, 100] degree
                        bool isRectangle = true;

                        // create a line segment from points
                        Point[]         pts   = approxContour.ToArray();
                        LineSegment2D[] edges = PointCollection.PolyLine(pts, true);

                        for (int j = 0; j < edges.Length; j++)
                        { // go trough all edges of a potential rectangle
                            // get angle between two adjcent edges
                            double angle = Math.Abs(edges[(j + 1) % edges.Length].GetExteriorAngleDegree(edges[j]));
                            if (angle < 80 || angle > 100)
                            {
                                isRectangle = false;
                                break;
                            }
                        }

                        if (isRectangle)
                        {
                            rectangles.Add(CvInvoke.MinAreaRect(approxContour)); // if it's a rectangle add it to the list
                        }
                    }
                    else if (approxContour.Size == 6 && detectHexagons)
                    { // hexagon
                        // Determine if all the angles in the contour are within [50, 70] degree
                        bool isHexagon = true;

                        // create a line segment from points
                        Point[]         pts   = approxContour.ToArray();
                        LineSegment2D[] edges = PointCollection.PolyLine(pts, true);

                        for (int j = 0; j < edges.Length; j++)
                        { // go trough all edges of a potential hexagon
                            // get angle between two adjcent edges
                            double angle = Math.Abs(edges[(j + 1) % edges.Length].GetExteriorAngleDegree(edges[j]));
                            if (angle < 50 || angle > 70)
                            {
                                isHexagon = false;
                                break;
                            }
                        }

                        if (isHexagon)
                        { // if it's a hexagon add it to the list
                            hexagons.Add(edges);
                        }
                    }
                }
            }
        }
Beispiel #7
0
        private void FindStopSign(Image <Bgr, byte> img, List <Image <Gray, Byte> > stopSignList, List <Rectangle> boxList, VectorOfVectorOfPoint contours, int[,] hierachy, int idx)
        {
            for (; idx >= 0; idx = hierachy[idx, 0])
            {
                using (VectorOfPoint c = contours[idx])
                    using (VectorOfPoint approx = new VectorOfPoint())
                    {
                        CvInvoke.ApproxPolyDP(c, approx, CvInvoke.ArcLength(c, true) * 0.02, true);
                        double area = CvInvoke.ContourArea(approx);
                        if (area > 200)
                        {
                            double ratio = CvInvoke.MatchShapes(_octagon, approx, Emgu.CV.CvEnum.ContoursMatchType.I3);

                            if (ratio > 0.1) //not a good match of contour shape
                            {
                                //check children
                                if (hierachy[idx, 2] >= 0)
                                {
                                    FindStopSign(img, stopSignList, boxList, contours, hierachy, hierachy[idx, 2]);
                                }
                                continue;
                            }

                            Rectangle box = CvInvoke.BoundingRectangle(c);

                            Image <Gray, Byte> candidate;
                            using (Image <Bgr, Byte> tmp = img.Copy(box))
                                candidate = tmp.Convert <Gray, byte>();
                            //Emgu.CV.UI.ImageViewer.Show(candidate);
                            //set the value of pixels not in the contour region to zero
                            using (Image <Gray, Byte> mask = new Image <Gray, byte>(box.Size))
                            {
                                mask.Draw(contours, idx, new Gray(255), -1, LineType.EightConnected, null, int.MaxValue, new Point(-box.X, -box.Y));

                                double mean = CvInvoke.Mean(candidate, mask).V0;
                                candidate._ThresholdBinary(new Gray(mean), new Gray(255.0));
                                candidate._Not();
                                mask._Not();
                                candidate.SetValue(0, mask);
                            }

                            int              minMatchCount         = 8;
                            double           uniquenessThreshold   = 0.8;
                            VectorOfKeyPoint _observeredKeypoint   = new VectorOfKeyPoint();
                            Mat              _observeredDescriptor = new Mat();
                            _detector.DetectAndCompute(candidate, null, _observeredKeypoint, _observeredDescriptor, false);

                            if (_observeredKeypoint.Size >= minMatchCount)
                            {
                                int k = 2;
                                //Matrix<int> indices = new Matrix<int>(_observeredDescriptor.Size.Height, k);
                                Matrix <byte> mask;
                                //using (Matrix<float> dist = new Matrix<float>(_observeredDescriptor.Size.Height, k))
                                using (VectorOfVectorOfDMatch matches = new VectorOfVectorOfDMatch())
                                {
                                    _modelDescriptorMatcher.KnnMatch(_observeredDescriptor, matches, k, null);
                                    mask = new Matrix <byte>(matches.Size, 1);
                                    mask.SetValue(255);
                                    Features2DToolbox.VoteForUniqueness(matches, uniquenessThreshold, mask);
                                }

                                int nonZeroCount = CvInvoke.CountNonZero(mask);
                                if (nonZeroCount >= minMatchCount)
                                {
                                    boxList.Add(box);
                                    stopSignList.Add(candidate);
                                }
                            }
                        }
                    }
            }
        }
        public static (ShapeType, List <Point>) Check(List <Point> polygonPoints, int canvasWidth, int canvasHeigth)
        {
            if (!ClosedContour(polygonPoints))
            {
                return(ShapeType.None, null);
            }

            CreateBitmap(canvasWidth, canvasHeigth, polygonPoints);

            Image <Bgr, byte>  img       = new Image <Bgr, byte>(@"IMAGE.bmp");
            Image <Gray, byte> processed = img
                                           .Convert <Gray, byte>()
                                           .SmoothGaussian(5)
                                           .Canny(240, 200);

            VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
            Mat m = new Mat();

            CvInvoke.FindContours(
                processed, contours, m, Emgu.CV.CvEnum.RetrType.External,
                Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple);

            if (contours.Size == 0)
            {
                return(ShapeType.None, null);
            }

            double perimeter = CvInvoke.ArcLength(contours[0], true);

            var polygon = new VectorOfPoint();

            CvInvoke.ApproxPolyDP(contours[0], polygon, 0.02 * perimeter, true);

            if (!CvInvoke.IsContourConvex(polygon))
            {
                return(ShapeType.None, null);
            }

            var   moments = CvInvoke.Moments(contours[0]);
            int   x       = (int)(moments.M10 / moments.M00);
            int   y       = (int)(moments.M01 / moments.M00);
            Point center  = new Point(x, y);

            List <Point> points = new List <Point>();

            for (int i = 0; i < polygon.Size; i++)
            {
                points.Add(new Point(polygon[i].X, polygon[i].Y));
            }

            if (points.Count == 3)
            {
                return(ShapeType.Triangle, points);
            }
            else if (points.Count == 4)
            {
                return(RectangleOrSquare(center, perimeter, points));
            }
            else if (points.Count > 4)
            {
                return(CircleOrEllipse(center, perimeter, points));
            }

            return(ShapeType.None, null);
        }
Beispiel #9
0
        public static IEnumerable <Rectangle> DetectSquares(Mat sourceImage)
        {
            Mat destinationImage = new Mat();

            destinationImage.Create(sourceImage.Rows, sourceImage.Cols, sourceImage.Depth, 1);
            Mat greyscaleImage = new Mat();

            CvInvoke.CvtColor(sourceImage, greyscaleImage, ColorConversion.Bgr2Gray);

            Mat detectedEdges = new Mat();

            CvInvoke.GaussianBlur(greyscaleImage, detectedEdges, new Size(1, 1), 1);
            CvInvoke.Canny(detectedEdges, detectedEdges, Treshold, Treshold * 3);
            CvInvoke.Dilate(detectedEdges, detectedEdges, new Mat(), new Point(-1, -1), 3, BorderType.Default, new MCvScalar(255, 255, 255));

            //ImageViewer.Show(detectedEdges);

            List <Rectangle> boxList = new List <Rectangle>();

            //List<LineSegment2D> lines = new List<LineSegment2D>();

            using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
            {
                CvInvoke.FindContours(detectedEdges, contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple);
                int count = contours.Size;
                for (int i = 0; i < count; i++)
                {
                    using (VectorOfPoint approxContour = new VectorOfPoint())
                        using (VectorOfPoint approx = contours[i])
                        {
                            CvInvoke.ApproxPolyDP(approx, approxContour, CvInvoke.ArcLength(approx, true) * 0.035, true);
                            Point[]         pts   = approxContour.ToArray();
                            LineSegment2D[] edges = PointCollection.PolyLine(pts, true);
                            //lines.AddRange(edges);

                            double contourArea = CvInvoke.ContourArea(approxContour, true);
                            if (contourArea >= 500 && contourArea <= detectedEdges.Width * detectedEdges.Height / 5)
                            {
                                if (approxContour.Size >= 2)
                                {
                                    bool isRectangle = true;

                                    for (int j = 0; j < edges.Length; j++)
                                    {
                                        double angle = Math.Abs(edges[(j + 1) % edges.Length]
                                                                .GetExteriorAngleDegree(edges[j]));

                                        if (angle < 85 || angle > 95)
                                        {
                                            isRectangle = false;
                                            break;
                                        }
                                    }

                                    if (isRectangle)
                                    {
                                        RotatedRect currentRectangle = CvInvoke.MinAreaRect(approxContour);
                                        Rectangle   minRectangle     = currentRectangle.MinAreaRect();
                                        //int ninetyPercentWidth = minRectangle.Width - (int)(minRectangle.Width * 0.05);
                                        //int ninetyPercentHeight = minRectangle.Height - (int)(minRectangle.Height * 0.05);
                                        //minRectangle.Size = new Size(ninetyPercentWidth, ninetyPercentHeight);
                                        //minRectangle.Offset(5, 5);
                                        boxList.Add(minRectangle);
                                    }
                                }
                            }
                        }
                }
            }

            return(boxList);
        }
Beispiel #10
0
        void ProcessFrame(object sender, EventArgs e)
        {
            Mat frame         = _cameraCapture.QueryFrame();
            Mat smoothedFrame = new Mat();

            CvInvoke.GaussianBlur(frame, smoothedFrame, new Size(3, 3), 1); //filter out noises

            #region use the BG/FG detector to find the foreground mask
            Mat foregroundMask = new Mat();
            _fgDetector.Apply(smoothedFrame, foregroundMask);
            #endregion

            List <TrackedObject> toBeRemovedList      = new List <TrackedObject>();
            List <Rectangle>     boundingBoxesTracked = new List <Rectangle>();
            List <int>           idsTracked           = new List <int>();

            foreach (TrackedObject t in _trackers)
            {
                Rectangle boundingBox;
                bool      success = t.Update(frame, out boundingBox);
                if (success)
                {
                    boundingBoxesTracked.Add(boundingBox);
                    idsTracked.Add(t.Id);
                }
                else
                {
                    toBeRemovedList.Add(t);
                }
            }

            foreach (TrackedObject t in toBeRemovedList)
            {
                _trackers.Remove(t);
                t.Dispose();
            }

            List <Rectangle> newObjects = new List <Rectangle>();
            int minAreaThreshold        = 100;
            using (Mat canny = new Mat())
                using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
                {
                    CvInvoke.Canny(foregroundMask, canny, 180, 100);
                    CvInvoke.FindContours(canny, contours, null, RetrType.External, ChainApproxMethod.ChainApproxSimple);
                    int count = contours.Size;
                    for (int i = 0; i < count; i++)
                    {
                        using (VectorOfPoint contour = contours[i])
                            using (VectorOfPoint approxContour = new VectorOfPoint())
                            {
                                CvInvoke.ApproxPolyDP(contour, approxContour, CvInvoke.ArcLength(contour, true) * 0.05, true);
                                if (CvInvoke.ContourArea(approxContour, false) > minAreaThreshold) //only consider contours with area greater than threshold
                                {
                                    Rectangle r          = CvInvoke.BoundingRectangle(approxContour);
                                    bool      overlapped = false;
                                    foreach (var trackedObj in boundingBoxesTracked)
                                    {
                                        if (r.IntersectsWith(trackedObj))
                                        {
                                            overlapped = true;
                                            break;
                                        }
                                    }
                                    if (!overlapped)
                                    {
                                        newObjects.Add(r);
                                    }
                                }
                            }
                    }
                }

            foreach (Rectangle r in newObjects)
            {
                TrackedObject t = new TrackedObject(_idCounter);
                boundingBoxesTracked.Add(r);
                idsTracked.Add(_idCounter);
                t.Init(frame, r);
                _trackers.Add(t);
                _idCounter++;
            }

            for (int i = 0; i < boundingBoxesTracked.Count; i++)
            {
                Rectangle boundingBox = boundingBoxesTracked[i];
                CvInvoke.Rectangle(frame, boundingBox, new MCvScalar(255.0, 255.0, 255.0), 2);
                CvInvoke.PutText(frame, idsTracked[i].ToString(), new Point(boundingBox.X, boundingBox.Y), FontFace.HersheyPlain,
                                 1.0, new MCvScalar(255.0, 255.0, 255.0));
            }

            imageBox1.Image = frame;
            imageBox2.Image = foregroundMask;
        }
Beispiel #11
0
        public Image <Bgr, byte> ReturnContours(Image <Bgr, byte> image, int minArea, Label label)
        {
            if (prepImage == null)
            {
                prepImage = ReturnBinarized(image, 90);
            }
            var resultImage = prepImage.Convert <Gray, byte>();
            int trisCount   = 0;
            int rectCount   = 0;
            int circleCount = 0;
            // shapes
            var contours = new VectorOfVectorOfPoint();

            CvInvoke.FindContours(
                resultImage,
                contours,
                null,
                RetrType.List,
                ChainApproxMethod.ChainApproxSimple);

            var contoursImage = sourceImage.Copy();

            for (int i = 0; i < contours.Size; i++)
            {
                //contoursImage.Draw(points, new Bgr(Color.GreenYellow), 2); // отрисовка точек

                var approxContour = new VectorOfPoint();
                CvInvoke.ApproxPolyDP(contours[i], approxContour, CvInvoke.ArcLength(contours[i], true) * 0.05, true);
                var points = approxContour.ToArray();
                if (approxContour.Size == 3)
                {
                    var S = CvInvoke.ContourArea(approxContour, false);
                    if (S > minArea)
                    {
                        trisCount++;
                        var pointsTri = approxContour.ToArray();
                        contoursImage.Draw(new Triangle2DF(pointsTri[0], pointsTri[1], pointsTri[2]), new Bgr(Color.GreenYellow), 2);
                    }
                }
                if (isRectangle(points))
                {
                    var S = CvInvoke.ContourArea(approxContour, false);
                    if (S > minArea)
                    {
                        rectCount++;
                        contoursImage.Draw(CvInvoke.MinAreaRect(approxContour), new Bgr(Color.Blue), 2);
                    }
                }
            }

            //circles

            List <CircleF> circles = new List <CircleF>(CvInvoke.HoughCircles(resultImage, HoughModes.Gradient, 1.0, 250, 100, 50, 5, contoursImage.Width / 3));

            foreach (CircleF circle in circles)
            {
                CvInvoke.Circle(contoursImage, Point.Round(circle.Center), (int)circle.Radius, new Bgr(Color.Red).MCvScalar, 2);
                circleCount++;
                //resultImage.Draw(circle, new Bgr(Color.GreenYellow), 2);
            }
            label.Text = "Количество треугольников = " + trisCount + "\nКоличество прямоугольников = " + rectCount + "\nКоличество кругов = " + circleCount;
            return(contoursImage);
        }
        // Maximum Value, Minimum Value and their locations
        // Mean Color or Mean Intensity

        public void calcularRegionProps(Image <Gray, byte> inputRegionIMG, double AreaMin)
        {
            // Declaração do vetor de vetores de pontos
            Emgu.CV.Util.VectorOfVectorOfPoint vetordeVetdePontos = new Emgu.CV.Util.VectorOfVectorOfPoint();
            // Declaração de uma matriz
            Mat hierarquia = new Mat();

            // Aplicação da função FindContour
            CvInvoke.FindContours(
                inputRegionIMG                                       // Recebe a imagem de entrada
                , vetordeVetdePontos                                 // Recebe um vetor de pontos de contorno
                , hierarquia                                         // Recebe a hierarquia dos pontos
                , Emgu.CV.CvEnum.RetrType.Tree                       // Recebe o tipo de arvore e contornos
                , Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxNone   // Tip de aproximação aos contornos
                , new Point(0, 0)                                    // Offset do ponto, posso omitir ou declarar um ponto a 0 0
                );

            Image <Bgr, Byte> input = inputRegionIMG.Convert <Bgr, byte>();

            //Até aqui encontro o contorno. Deve ser só 1!!!, portanto deve ser o contorno 0,
            //mas mesmo assim vamos fazer um teste para ver qual o contorno a usar

            // Pontos buffer
            PointF buffer_Minx = new PointF(inputRegionIMG.Width, inputRegionIMG.Height);
            PointF buffer_MaxX = new PointF(0, 0);
            PointF buffer_MinY = new PointF(inputRegionIMG.Width, inputRegionIMG.Height);
            PointF buffer_MaxY = new PointF(0, 0);


            for (int i = 0; i < vetordeVetdePontos.Size; i++)
            {
                Area = Math.Abs(CvInvoke.ContourArea(vetordeVetdePontos[i], true));      // calcula a area do contorno

                if (Area >= AreaMin)
                {
                    for (int iter = 0; iter < vetordeVetdePontos[i].Size; iter++)
                    {
                        //----------------- Calculo do extreme -----------------
                        // Calcula o valor do ponto mais à esquerda
                        if (vetordeVetdePontos[i][iter].X < buffer_Minx.X)
                        {
                            buffer_Minx = vetordeVetdePontos[i][iter];
                        }

                        // Calcula o valor do ponto mais à direita
                        if (vetordeVetdePontos[i][iter].X > buffer_MaxX.X)
                        {
                            buffer_MaxX = vetordeVetdePontos[i][iter];
                        }

                        // Calcula o valor do ponto Y mais em cima
                        if (vetordeVetdePontos[i][iter].Y < buffer_MinY.Y)
                        {
                            buffer_MinY = vetordeVetdePontos[i][iter];
                        }

                        // Calcula o valor do ponto Y mais em baixo
                        if (vetordeVetdePontos[i][iter].Y > buffer_MaxY.Y)
                        {
                            buffer_MaxY = vetordeVetdePontos[i][iter];
                        }
                        //----------------- Fim do calculo do extreme -----------------
                    }

                    // ------------- Calculo do Centroid ---------------------
                    Moments momento = CvInvoke.Moments(vetordeVetdePontos[i]);
                    int     X       = (int)(momento.M10 / momento.M00);
                    int     Y       = (int)(momento.M01 / momento.M00);
                    Centroid = new PointF(X, Y);
                    // ------------------------------------------------------

                    // ------------ Calculo do AspectRatio ------------------
                    AspectRatio = inputRegionIMG.Width / inputRegionIMG.Height;
                    //-------------------------------------------------------

                    //------------- Calculo da BoundingBox ------------------
                    BoundingBox = CvInvoke.BoundingRectangle(vetordeVetdePontos[i]);
                    //-------------------------------------------------------

                    // ------------   Calculo do Extent   -------------------
                    float rect_area = BoundingBox.Width * BoundingBox.Height;
                    Extent = (float)Area / rect_area;
                    // ------------------------------------------------------

                    // --------------- ConvectHULL --------------------------
                    CvInvoke.ConvexHull(vetordeVetdePontos[i], ConvexHull, false);
                    //-------------------------------------------------------

                    // --------------- ConvectHULL_area ---------------------
                    ConvexHull_area = CvInvoke.ContourArea(ConvexHull);
                    //-------------------------------------------------------

                    //-----------------  Solidity ---------------------------
                    Solidity = Area / ConvexHull_area;
                    // ------------------------------------------------------

                    //-------------- Diametro Equivalente -------------------
                    EquivalentDiameter = Math.Sqrt(4 * Area / Math.PI);
                    // ------------------------------------------------------

                    //--------------- Circulo Envolvente --------------------
                    CirculoEnvolvente = CvInvoke.MinEnclosingCircle(vetordeVetdePontos[i]);
                    //-------------------------------------------------------

                    //--------------- Circulo Perimetro --------------------
                    perimetro = CvInvoke.ArcLength(vetordeVetdePontos[i], true);
                    // -----------------------------------------------------

                    // -------------- Circularity (Fator de forma)----------
                    Circularity = (4 * Math.PI * Area) / (perimetro * perimetro);
                    //------------------------------------------------------

                    // --------------- Verifica se é convexo ---------------
                    isConvex = CvInvoke.IsContourConvex(vetordeVetdePontos[i]);
                    //------------------------------------------------------

                    // ------------- Apriximação do contorno ---------------
                    CvInvoke.ApproxPolyDP(
                        vetordeVetdePontos[i],              // Cada vetor de um contorno iterado
                        ContourApproximation,               // Vetor que vai conter a aproximação
                        0.1 * perimetro,                    // Expande o perimetro
                        true                                // Calcula um aproximação ao contorno externo
                        );
                    // -----------------------------------------------------

                    // ------------- Devolve o contorno --------------------
                    Contorno = vetordeVetdePontos[i];
                    // ------------------------------------------------------

                    // ------------  Retangulo rodado  ---------------------
                    RotatedRect retanguloRodado = CvInvoke.MinAreaRect(vetordeVetdePontos[i]);
                    PointF[]    vetorPontos     = CvInvoke.BoxPoints(retanguloRodado);
                    BoundingBoxRectRodado = new Point[vetorPontos.Length];
                    for (int iterador = 0; iterador < vetorPontos.Length; iterador++)
                    {
                        BoundingBoxRectRodado[iterador].X = (int)vetorPontos[iterador].X;
                        BoundingBoxRectRodado[iterador].Y = (int)vetorPontos[iterador].Y;
                    }
                    // ------------ AnguloRecExterior ----------------------
                    AnguloRectExterior = retanguloRodado.Angle;
                    // -----------------------------------------------------

                    // ------------ EllipseImagem --------------------------
                    EllipseValores = CvInvoke.FitEllipseAMS(vetordeVetdePontos[i]);
                    // -----------------------------------------------------

                    // Fitting a Line ---------------
                    //---------------------------

                    // salta do ciclo for
                    i = vetordeVetdePontos.Size;
                }
            }

            Extreme.Mais_a_esquerda = buffer_Minx;
            Extreme.Mais_a_Direita  = buffer_MaxX;
            Extreme.Mais_em_baixo   = buffer_MaxY;
            Extreme.Mais_em_cima    = buffer_MinY;
        }
        private Mat DoCalibration(Image <Bgr, byte> medianBlurImageIn)
        {
            DebugImages[(int)SelectedImage.InImageB] = medianBlurImageIn[0].Mat;
            DebugImages[(int)SelectedImage.InImageG] = medianBlurImageIn[1].Mat;
            DebugImages[(int)SelectedImage.InImageR] = medianBlurImageIn[2].Mat;

            var InImageSum = medianBlurImageIn[0] + medianBlurImageIn[1] + medianBlurImageIn[2];

            DebugImages[(int)SelectedImage.InImageSum] = InImageSum.Mat;

            Mat threshold = new Mat();

            CvInvoke.Threshold(InImageSum, threshold, Parameters.Threshold, 255, ThresholdType.Binary);
            DebugImages[(int)SelectedImage.threshold] = threshold;

            Mat CannyImage = new Mat();

            CvInvoke.Canny(threshold, CannyImage, Parameters.CannyThreshold1, Parameters.CannyThreshold2, 3, true);
            DebugImages[(int)SelectedImage.Canny] = CannyImage;


            var contoursImage = medianBlurImageIn.Clone();

            DebugImages[(int)SelectedImage.approxContour] = contoursImage.Mat;

            using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
            {
                CvInvoke.FindContours(CannyImage, contours, null, RetrType.External, ChainApproxMethod.ChainApproxNone);

                VectorOfPoint maxContour = null;
                double        arcSize    = -1;

                for (int i = 0; i < contours.Size; i++)
                {
                    var arc = CvInvoke.ArcLength(contours[i], true);
                    if (arc > arcSize)
                    {
                        arcSize    = arc;
                        maxContour = contours[i];
                    }
                }
                if (maxContour != null)
                {
                    using (VectorOfPoint approxContour = new VectorOfPoint())
                    {
                        CvInvoke.ApproxPolyDP(maxContour, approxContour, Parameters.ContourEpsilon, true);
                        var convexContour      = CvInvoke.ConvexHull(approxContour.ToArray().Select((x) => new PointF(x.X, x.Y)).ToArray());
                        var pointConvexContour = convexContour.Select((x) => new Point((int)x.X, (int)x.Y)).ToArray();

                        var circle = CvInvoke.MinEnclosingCircle(convexContour);

                        if (convexContour.Length == 6 && validateAsked)
                        {
                            validateAsked = false;

                            Parameters.Center = new Point((int)circle.Center.X, (int)circle.Center.Y);

                            var maxY = convexContour.Max((x) => x.Y);

                            var indexSommetHaut = convexContour.ToList().FindIndex((x) => x.Y >= maxY - 0.1);

                            for (int i = indexSommetHaut; i < convexContour.Length; i++)
                            {
                                Parameters.Points[i] = pointConvexContour[i];
                            }

                            for (int i = 0; i < indexSommetHaut; i++)
                            {
                                Parameters.Points[i] = pointConvexContour[i];
                            }

                            grid.Refresh();
                            Save();
                            chkAutoCalibration.Checked = false;
                        }

                        contoursImage.DrawPolyline(pointConvexContour, true, new Bgr(Color.Green), 3);

                        contoursImage.Draw(circle, new Bgr(Color.DarkGreen), 3);

                        contoursImage.Draw(new Cross2DF(circle.Center, 10, 10), new Bgr(Color.DarkGreen), 3);
                    }
                }

                return(DebugImages[(int)Parameters.SelectedImage]);
            }
        }
Beispiel #14
0
        public void DisplayWebcam(popup popup)
        {
            while (true)
            {
                Mat          frame         = ReadCamera1();
                int          largestCircle = 0;
                List <Shape> foundShape    = new List <Shape>();
                List <char>  shapeType     = new List <char>();


                // resize to PictureBox aspect ratio
                int  newHeight = (frame.Size.Height * pictureBox0.Size.Width) / frame.Size.Width;
                Size newSize   = new Size(pictureBox0.Size.Width, newHeight);
                CvInvoke.Resize(frame, frame, newSize);

                Image <Hsv, Byte>  img               = frame.ToImage <Hsv, Byte>();
                Image <Gray, byte> coralNestImg      = frame.ToImage <Gray, Byte>();
                Image <Gray, byte> coralOutcropImg   = frame.ToImage <Gray, Byte>();
                Image <Gray, byte> starfishImg       = frame.ToImage <Gray, Byte>();
                Image <Bgr, byte>  drawnImage        = frame.ToImage <Bgr, byte>();
                Image <Bgr, byte>  coralNestDrawn    = frame.ToImage <Bgr, byte>();
                Image <Bgr, byte>  coralOutcropDrawn = frame.ToImage <Bgr, byte>();
                Image <Bgr, byte>  starfishDrawn     = frame.ToImage <Bgr, byte>();
                Image <Gray, byte> gridImg           = frame.ToImage <Gray, Byte>();
                Image <Bgr, byte>  gridDrawn         = frame.ToImage <Bgr, byte>();

                //Line Follow
                Hsv T_Lower = new Hsv(colorThresholds[4].h_Lower, colorThresholds[4].s_Lower, colorThresholds[4].v_Lower);
                Hsv T_Upper = new Hsv(colorThresholds[4].h_Upper, colorThresholds[4].s_Upper, colorThresholds[4].v_Upper);
                Image <Gray, byte> laneImg = frame.ToImage <Gray, Byte>();
                laneImg = img.InRange(T_Lower, T_Upper).Erode(2).Dilate(2);

                //count for columbs
                int leftC   = 0;
                int centerC = 0;
                int rightC  = 0;


                for (int i = (laneImg.Height / 20) * 15; i < laneImg.Height; i++)
                {
                    for (int j = (laneImg.Width / 20) * 14; j < (laneImg.Width / 20) * 16; j++)
                    {
                        //left
                        if (laneImg.Data[i, j, 0] == 255)
                        {
                            leftC++;
                        }
                    }
                    for (int j = (laneImg.Width / 20) * 16; j < (laneImg.Width / 20) * 18; j++)
                    {
                        //center
                        if (laneImg.Data[i, j, 0] == 255)
                        {
                            centerC++;
                        }
                    }
                    for (int j = (laneImg.Width / 20) * 18; j < (laneImg.Width / 20) * 20; j++)
                    {
                        //right
                        if (laneImg.Data[i, j, 0] == 255)
                        {
                            rightC++;
                        }
                    }
                }

                if (leftC > centerC && leftC > rightC)
                {
                    //twist left
                    Twist twist = new Twist();
                    twist.Linear.Z = 1f;
                    SetInput(twist);
                    label7.Invoke(new Action(() => {
                        label7.Text = "left";
                    }));
                }
                else
                {
                    if (centerC > rightC && centerC > leftC)
                    {
                        // twist center
                        Twist twist = new Twist();
                        twist.Linear.X = 1f;
                        SetInput(twist);
                        label7.Invoke(new Action(() => {
                            label7.Text = "center";
                        }));
                    }
                    else
                    {
                        //twist right
                        Twist twist = new Twist();
                        twist.Linear.Z = -1f;
                        SetInput(twist);

                        label7.Invoke(new Action(() => {
                            label7.Text = "right";
                        }));
                    }
                }

                if (leftC + rightC + centerC <= 100)
                {
                    Twist twist = new Twist();
                    twist.Linear.X = 0;
                    SetInput(twist);
                    //Update keys
                    popup.UpdateKeys(key);
                }

                // Find Centers and Draw Bounding Rectangle
                for (int i = 0; i < 3; i++)
                {
                    VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
                    List <Shape>          shapes   = new List <Shape>();
                    Mat    draw        = new Mat();
                    Hsv    t_Lower     = new Hsv(colorThresholds[i].h_Lower, colorThresholds[i].s_Lower, colorThresholds[i].v_Lower);
                    Hsv    t_Upper     = new Hsv(colorThresholds[i].h_Upper, colorThresholds[i].s_Upper, colorThresholds[i].v_Upper);
                    int    shapeIndex  = 0;
                    double largestArea = 0;
                    switch (i)
                    {
                    case 0:
                        coralNestImg = img.InRange(t_Lower, t_Upper).Erode(2).Dilate(2);
                        CvInvoke.FindContours(coralNestImg, contours, draw, Emgu.CV.CvEnum.RetrType.Ccomp, ChainApproxMethod.ChainApproxSimple);
                        break;

                    case 1:
                        coralOutcropImg = img.InRange(t_Lower, t_Upper).Erode(2).Dilate(2);
                        CvInvoke.FindContours(coralOutcropImg, contours, draw, Emgu.CV.CvEnum.RetrType.Ccomp, ChainApproxMethod.ChainApproxSimple);
                        break;

                    case 2:
                        starfishImg = img.InRange(t_Lower, t_Upper).Erode(2).Dilate(2);
                        CvInvoke.FindContours(starfishImg, contours, draw, Emgu.CV.CvEnum.RetrType.Ccomp, ChainApproxMethod.ChainApproxSimple);
                        break;

                    default:
                        break;
                    }


                    for (int j = 0; j < contours.Size; j++)
                    {
                        double        peramiter = CvInvoke.ArcLength(contours[j], true);
                        VectorOfPoint positions = new VectorOfPoint();
                        CvInvoke.ApproxPolyDP(contours[j], positions, 0.03 * peramiter, true);
                        var moments = CvInvoke.Moments((contours[j]));
                        shapes.Add(new Shape());
                        //Find Centroid of shape and area and store in shape class
                        shapes[j].x_Center = (moments.M10 / moments.M00);
                        shapes[j].y_Center = (moments.M01 / moments.M00);
                        shapes[j].area     = CvInvoke.ContourArea(contours[j]);
                    }
                    //Only compute if there are shapes on screen
                    if (shapes.Count > 0)
                    {
                        // find largest shape sstore it
                        for (int j = 0; j < shapes.Count; j++)
                        {
                            if (shapes[j].area > largestArea)
                            {
                                largestArea = shapes[j].area;
                                shapeIndex  = j;
                            }
                        }


                        Rectangle boundingRect = new Rectangle((int)(shapes[shapeIndex].x_Center - 50), (int)(shapes[shapeIndex].y_Center - 50), 100, 100);
                        switch (i)
                        {
                        case 0:
                            coralNestDrawn = coralNestImg.Convert <Bgr, byte>();
                            coralNestDrawn.Draw(boundingRect, new Bgr(0, 0, 255), 3, LineType.EightConnected, 0);
                            //Add to list of shapes found
                            foundShape.Add(shapes[shapeIndex]);
                            shapeType.Add('n');
                            break;

                        case 1:
                            coralOutcropDrawn = coralOutcropImg.Convert <Bgr, byte>();
                            coralOutcropDrawn.Draw(boundingRect, new Bgr(0, 0, 255), 3, LineType.EightConnected, 0);
                            //Add to list of shapes found
                            foundShape.Add(shapes[shapeIndex]);
                            shapeType.Add('o');
                            break;

                        case 2:
                            starfishDrawn = starfishImg.Convert <Bgr, byte>();
                            starfishDrawn.Draw(boundingRect, new Bgr(0, 0, 255), 3, LineType.EightConnected, 0);
                            //Add to list of shapes found
                            foundShape.Add(shapes[shapeIndex]);
                            shapeType.Add('s');
                            break;
                        }
                    }
                }
                //Circle Detection

                /*     //    var findEdges = img.SmoothGaussian((int)(colorThresholds[3].h_Upper)).Convert<Gray, byte>().ThresholdBinaryInv(new Gray(colorThresholds[3].s_Lower), new Gray(colorThresholds[3].s_Upper)).Erode((int)(colorThresholds[3].h_Lower)).Dilate((int)(colorThresholds[3].h_Lower));
                 *
                 *       Hsv c_Lower = new Hsv(colorThresholds[3].h_Lower, colorThresholds[3].s_Lower, colorThresholds[3].v_Lower);
                 *       Hsv c_Upper = new Hsv(colorThresholds[3].h_Upper, colorThresholds[3].s_Upper, colorThresholds[3].v_Upper);
                 *       Image<Gray, byte> findEdges = frame.ToImage<Gray, Byte>();
                 *       findEdges = img.InRange(c_Lower, c_Upper).Erode(2);
                 *
                 *       Gray cannyThreshold = new Gray(180);
                 *               Gray cannyThresholdLinking = new Gray(120);
                 *               Gray circleAccumulatorThreshold = new Gray(60);
                 *
                 *               CircleF[] foundCircles = findEdges.HoughCircles(
                 *                       cannyThreshold,
                 *                       circleAccumulatorThreshold,
                 *                       4.0, //Resolution of the accumulator used to detect centers of the circles
                 *                       4.0, //Resolution of the accumulator used to detect centers of the circles
                 *                       10.0, //min distance
                 *                       10, //min radius
                 *                       30 //max radius
                 *                       )[0]; //Get the circles from the first channel
                 *
                 *               drawnImage = findEdges.Convert<Bgr, Byte>();
                 *
                 *
                 *               // Find Largest Circle and Draw it on Frame
                 *               for (int j = 0; j < foundCircles.Length; j++)
                 *               {
                 *                       if (j == 0)
                 *                       {
                 *                               // Skip 0 because its the largest circle at this time
                 *                       }
                 *                       else
                 *                       {
                 *                               if (foundCircles[j].Area > foundCircles[largestCircle].Area) // Check to see if this is the Largest Circle
                 *                               {
                 *                                       largestCircle = j;
                 *                               }
                 *                       }
                 *               }
                 *               if (foundCircles.Length != 0)
                 *                       drawnImage.Draw(foundCircles[largestCircle], new Bgr(0, 255, 0), 3, LineType.EightConnected, 0); // Circle Draw
                 *
                 */


                // Grid Detection
                VectorOfVectorOfPoint Contours = new VectorOfVectorOfPoint();
                Mat Draw    = new Mat();
                Hsv g_Lower = new Hsv(colorThresholds[5].h_Lower, colorThresholds[5].s_Lower, colorThresholds[5].v_Lower);
                Hsv g_Upper = new Hsv(colorThresholds[5].h_Upper, colorThresholds[5].s_Upper, colorThresholds[5].v_Upper);
                gridImg = img.InRange(g_Lower, g_Upper).Erode(2).Dilate(2);
                CvInvoke.FindContours(coralNestImg, Contours, Draw, Emgu.CV.CvEnum.RetrType.Ccomp, ChainApproxMethod.ChainApproxSimple);
                List <Shape> gShapes = new List <Shape>();
                for (int j = 0; j < Contours.Size; j++)
                {
                    double        peramiter = CvInvoke.ArcLength(Contours[j], true);
                    VectorOfPoint positions = new VectorOfPoint();
                    CvInvoke.ApproxPolyDP(Contours[j], positions, 0.03 * peramiter, true);
                    var moments = CvInvoke.Moments((Contours[j]));
                    gShapes.Add(new Shape());
                    //Find Centroid of shape and area and store in shape class
                    gShapes[j].x_Center = (moments.M10 / moments.M00);
                    gShapes[j].y_Center = (moments.M01 / moments.M00);
                    gShapes[j].area     = CvInvoke.ContourArea(Contours[j]);
                }

                if (gShapes.Count > 0)
                {
                    for (int i = 0; i < gShapes.Count; i++)
                    {
                        if (gShapes[i].area > 400 || gShapes[i].area < 20000)
                        {
                            gShapes.RemoveAt(i);                             // remove unwanted shapes
                        }
                    }

                    /*
                     *                                      // outline grid squares found
                     *                                      gridDrawn = gridImg.Convert<Bgr, byte>();
                     *                                      for(int i =0;i<gShapes.Count; i++)
                     *                                      {
                     *                                              Rectangle boundingRect = new Rectangle((int)(gShapes[i].x_Center - 50), (int)(gShapes[i].y_Center - 50), 100, 100);
                     *                                              gridDrawn.Draw(boundingRect, new Bgr(0, 0, 255), 3, LineType.EightConnected, 0);
                     *                                      }
                     *
                     *                                      for(int i = 0; i < gShapes.Count; i++)
                     *                                      {
                     *                                              if (LastPosition.Count == 0)
                     *                                              {
                     *                                                      LastPosition.Add(gShapes[i]); // store shapes positions for next rotation
                     *                                                      start = 0;
                     *                                                      end = foundShape.Count;
                     *                                                      //check if centroids are close to those of found shapes
                     *                                                      for (int j = 0; j < foundShape.Count; j++)
                     *                                                      {
                     *                                                              // Check centerpoints with tolerance of +- 20
                     *                                                              if(((foundShape[j].x_Center < gShapes[i].x_Center + 20) && (foundShape[j].x_Center > gShapes[i].x_Center - 20)) && ((foundShape[j].y_Center < gShapes[i].y_Center + 20) && (foundShape[j].y_Center > gShapes[i].y_Center - 20)))
                     *                                                              {
                     *                                                                      key[i] = shapeType[j];
                     *                                                              }
                     *                                                      }
                     *
                     *                                              }
                     *                                              else
                     *                                              {
                     *                                                      int tEnd = 0;
                     *                                                      for(int j = 0; j < gShapes.Count; j++)
                     *                                                      {
                     *
                     *                                                              if (((LastPosition[j].x_Center < gShapes[i].x_Center + 10) && (LastPosition[j].x_Center > gShapes[i].x_Center - 10)) && ((LastPosition[j].y_Center < gShapes[i].y_Center + 10) && (LastPosition[j].y_Center > gShapes[i].y_Center - 10)))
                     *                                                              {
                     *                                                                      tEnd = j;
                     *                                                              }
                     *                                                              end = tEnd;
                     *                                                              start = (end - foundShape.Count);
                     *
                     *                                                      }
                     *
                     *                                                      for (int j = 0; j < gShapes.Count; j++)
                     *                                                      {
                     *
                     *                                                              if (((foundShape[j].x_Center < gShapes[i].x_Center + 20) && (foundShape[j].x_Center > gShapes[i].x_Center - 20)) && ((foundShape[j].y_Center < gShapes[i].y_Center + 20) && (foundShape[j].y_Center > gShapes[i].y_Center - 20)))
                     *                                                              {
                     *                                                                      key[i + start] = shapeType[j];
                     *                                                              }
                     *
                     *                                                      }
                     *                                              }
                     *                                      }
                     */
                }                 // Grid analysis

                // Display Images
                pictureBox0.Image = frame.Bitmap;
                pictureBox1.Image = coralNestDrawn.Bitmap;
                pictureBox2.Image = coralOutcropDrawn.Bitmap;
                pictureBox3.Image = starfishDrawn.Bitmap;
                pictureBox4.Image = drawnImage.Bitmap;
                pictureBox5.Image = laneImg.Bitmap;
                GridBox.Image     = gridDrawn.Bitmap;

                if (!Sleep(20))
                {
                    this.Invoke(new Action(() => { Close(); }));
                    break;
                }
            }
        }
Beispiel #15
0
        private void contours_Click(object sender, EventArgs e)
        {
            if (source == null)
            {
                MessageBox.Show("Please open an image.");
                return;
            }

            #region reset UI
            squareNum.Text   = "0";
            triangleNum.Text = "0";
            circleNum.Text   = "0";
            lineNum.Text     = "0";
            #endregion

            try {
                #region image manipulation

                int sg;
                int.TryParse(smoothGaussian.Text, out sg);

                int lowerBound;
                int.TryParse(lower.Text, out lowerBound);

                int upperBound;
                int.TryParse(upper.Text, out upperBound);

                var temp = source.SmoothGaussian(sg).Convert <Gray, byte>().ThresholdBinary(new Gray(lowerBound), new Gray(upperBound));;

                if (inverse.Checked)
                {
                    temp = source.SmoothGaussian(sg).Convert <Gray, byte>().ThresholdBinaryInv(new Gray(lowerBound), new Gray(upperBound));
                }
                if (pyr.Checked)
                {
                    CvInvoke.PyrDown(temp, temp);
                    CvInvoke.PyrUp(temp, temp);
                }
                processedImage.Image = temp.Bitmap;

                #endregion

                #region find contours

                VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();

                CvInvoke.FindContours(temp, contours, new Mat(), RetrType.External, ChainApproxMethod.ChainApproxSimple);

                #endregion

                #region guess shapes

                Image <Bgr, byte> final = source.Copy();

                double approxAmount;
                double.TryParse(approxValue.Text, out approxAmount);

                double minRatio;
                double maxRatio;
                double minArea;
                double.TryParse(ratioValue.Text, out minRatio);
                double.TryParse(marea.Text, out minArea);
                maxRatio = 1 / minRatio;

                double bx;
                double.TryParse(bounding.Text, out bx);

                for (int i = 0; i < contours.Size; i++)
                {
                    var           contour   = contours[i];
                    double        perimeter = CvInvoke.ArcLength(contour, true);
                    VectorOfPoint approx    = new VectorOfPoint();
                    CvInvoke.ApproxPolyDP(contour, approx, approxAmount * perimeter, true);

                    CvInvoke.DrawContours(final, contours, i, new MCvScalar(0, 0, 255), 1);
                    Rectangle bounds = CvInvoke.BoundingRectangle(contour);
                    final.Draw(bounds, new Bgr(255, 0, 0));
                    finalImage.Image = final.Bitmap;

                    double area = CvInvoke.ContourArea(contour);

                    if (!(bounds.X > bx && bounds.X < final.Width - bx))
                    {
                        if (messages.Checked)
                        {
                            MessageBox.Show("Not in bounds");
                        }
                        continue;
                    }

                    if (!(bounds.Y > bx && bounds.Y < final.Height - bx))
                    {
                        if (messages.Checked)
                        {
                            MessageBox.Show("Not in bounds");
                        }
                        continue;
                    }

                    if (area < minArea)
                    {
                        if (messages.Checked)
                        {
                            MessageBox.Show("Not large enough");
                        }
                        continue;
                    }

                    if (approx.Size == 3)
                    {
                        int current;
                        int.TryParse(triangleNum.Text, out current);
                        current         += 1;
                        triangleNum.Text = current.ToString();
                    }
                    else if (approx.Size == 4)
                    {
                        Point[] test = approx.ToArray();

                        Point a = test[0];
                        Point b = test[1];
                        Point c = test[2];

                        double width  = Math.Sqrt((((double)(a.X - b.X)) * ((double)(a.X - b.X))) + (((double)(a.Y - b.Y)) * ((double)(a.Y - b.Y))));
                        double height = Math.Sqrt((((double)(c.X - b.X)) * ((double)(c.X - b.X))) + (((double)(c.Y - b.Y)) * ((double)(c.Y - b.Y))));

                        double ratio = width / height;
                        int    current;
                        if (ratio > minRatio && ratio < maxRatio)
                        {
                            int.TryParse(squareNum.Text, out current);
                            current       += 1;
                            squareNum.Text = current.ToString();
                        }
                        else
                        {
                            int.TryParse(lineNum.Text, out current);
                            current     += 1;
                            lineNum.Text = current.ToString();
                        }
                    }
                    else
                    {
                        int current;
                        int.TryParse(circleNum.Text, out current);
                        current       += 1;
                        circleNum.Text = current.ToString();
                    }
                    if (messages.Checked)
                    {
                        MessageBox.Show("Current shape: " + approx.Size.ToString());
                    }
                }

                #endregion
            } catch (Exception exception) {
                MessageBox.Show(exception.Message);
            }
        }
        /// <summary>
        /// Поиск знака. Метод Кенни (поиск по границам)
        /// </summary>
        /// <param name="img">Исходное изображение</param>
        /// <param name="brickSingList">Список знаков на изображении</param>
        /// <param name="boxList">Список областей со знаком</param>
        /// <param name="contours">Контур</param>
        /// <param name="hierachy"></param>
        /// <param name="idx"></param>
        private void FindBrickSing(Mat img, List <Mat> brickSingList, List <Rectangle> boxList, VectorOfVectorOfPoint contours, int[,] hierachy, int idx)
        {
            for (; idx >= 0; idx = hierachy[idx, 0])
            {
                using (VectorOfPoint c = contours[idx])
                    using (VectorOfPoint approx = new VectorOfPoint())
                    {
                        CvInvoke.ApproxPolyDP(c, approx, CvInvoke.ArcLength(c, true) * 0.02, true);
                        double area = CvInvoke.ContourArea(approx);

                        if (area > 200)
                        {
                            double ratio = CvInvoke.MatchShapes(_octagon, approx, ContoursMatchType.I3);

                            if (ratio > 0.1) //Подходящих совпадений не найдено
                            {
                                if (hierachy[idx, 2] >= 0)
                                {
                                    FindBrickSing(img, brickSingList, boxList, contours, hierachy, hierachy[idx, 2]);
                                }
                                continue;
                            }

                            Rectangle box = CvInvoke.BoundingRectangle(c);

                            Mat candidate = new Mat();

                            //Поиск кандидата на искомое вхождение
                            using (Mat tmp = new Mat(img, box))
                            {
                                CvInvoke.CvtColor(tmp, candidate, ColorConversion.Bgr2Gray);
                            }

                            //Устанавливаем значение пикселей вне контура равным нулю
                            using (Mat mask = new Mat(candidate.Size.Height, candidate.Width, DepthType.Cv8U, 1))
                            {
                                mask.SetTo(new MCvScalar(0));
                                CvInvoke.DrawContours(mask, contours, idx, new MCvScalar(255), -1, LineType.EightConnected, null, int.MaxValue, new Point(-box.X, -box.Y));
                                double mean = CvInvoke.Mean(candidate, mask).V0;

                                CvInvoke.Threshold(candidate, candidate, mean, 255, ThresholdType.Binary);
                                CvInvoke.BitwiseNot(candidate, candidate);
                                CvInvoke.BitwiseNot(mask, mask);

                                candidate.SetTo(new MCvScalar(0), mask);
                            }

                            int              minMatchCount        = 0;
                            double           uniquenessThreshold  = 0.0;
                            VectorOfKeyPoint observaredKeyPoint   = new VectorOfKeyPoint();
                            Mat              observeredDescriptor = new Mat();
                            _detector.DetectAndCompute(candidate, null, observaredKeyPoint, observeredDescriptor, false);

                            //Обозначаем искомое вхождение
                            if (observaredKeyPoint.Size >= minMatchCount)
                            {
                                int i = 2;
                                Mat mask;

                                using (VectorOfVectorOfDMatch matches = new VectorOfVectorOfDMatch())
                                {
                                    _modelDescriptorMatcher.KnnMatch(observeredDescriptor, matches, i, null);
                                    mask = new Mat(matches.Size, 1, DepthType.Cv8U, 1);
                                    Features2DToolbox.VoteForUniqueness(matches, uniquenessThreshold, mask);
                                }

                                int nonZeroCount = CvInvoke.CountNonZero(mask);

                                if (nonZeroCount >= minMatchCount)
                                {
                                    boxList.Add(box);
                                    brickSingList.Add(candidate);
                                }
                            }
                        }
                    }
            }
        }
Beispiel #17
0
        public List <CircleF> HoughCircles(Image <Bgr, byte> EyeRoi, // Input image
                                           int minRadius,            // Circle Radius
                                           int maxRadius,
                                           double dp         = 0.1,  // Resolution of the accumulator used to detect centers of the circles
                                           double minDist    = 0.01, //min detected circles distance
                                           double CannyThres = 80,   // Canny high threshold
                                           double HoughThres = 80    // Hough counting threshold
                                           )
        {
            //轉灰階
            img_Gray = EyeRoi.Convert <Gray, Byte>();
            img_Gray._GammaCorrect(0.6);
            img_Bgr = EyeRoi.Clone();
            // Laplace 邊緣強化
            img_laplace = img_Gray.Convert <Gray, float>();
            //Convert to 8-bit image
            Point[]  minLoc, maxLoc;
            double[] mins, maxs;
            img_laplace.MinMax(out mins, out maxs, out minLoc, out maxLoc);
            img_laplaceByte = img_laplace.ConvertScale <byte>(255 / maxs[0], 0);

            img_Sobel  = img_laplaceByte.Convert <Gray, float>();
            img_SobelX = img_laplaceByte.Sobel(1, 0, 3);
            img_SobelY = img_laplaceByte.Sobel(0, 1, 3);

            img_SobelX = img_SobelX.AbsDiff(new Gray(0));
            img_SobelY = img_SobelY.AbsDiff(new Gray(0));
            img_Sobel  = img_SobelX + img_SobelY;
            //Find sobel min or max value

            //Find sobel min or max value position
            img_Sobel.MinMax(out mins, out maxs, out minLoc, out maxLoc);
            //Conversion to 8-bit image
            sobelImage = img_Sobel.ConvertScale <byte>(255 / maxs[0], 0);


            //Adaptive Threshold
            img_Ada = img_Gray.Clone();
            CvInvoke.AdaptiveThreshold(img_laplaceByte, img_Ada, 255, AdaptiveThresholdType.GaussianC, ThresholdType.Binary, 7, 0);
            img_Threshold = img_Ada.Clone();

            //Median Filter
            CvInvoke.MedianBlur(img_Threshold, img_Threshold, 3);

            // Canny
            img_Edge = img_Gray.CopyBlank();
            img_Edge = img_Threshold.Canny(30, 90);

            VectorOfVectorOfPoint Contours = new VectorOfVectorOfPoint();
            List <VectorOfPoint>  C        = new List <VectorOfPoint>();

            CvInvoke.FindContours(img_Edge, Contours, null, RetrType.External, ChainApproxMethod.ChainApproxNone);
            img_Edge     = img_Gray.CopyBlank();
            img_EdgeText = EyeRoi.CopyBlank();

            double maxLen = 0;
            int    Inx    = 0;

            if (Contours.Size > 0)
            {
                for (int i = 0; i < Contours.Size; i++)
                {
                    double len = CvInvoke.ArcLength(Contours[i], true);
                    if (len > maxLen)
                    {
                        maxLen = len;
                        Inx    = i;
                    }
                    CvInvoke.DrawContours(img_Edge, Contours, i, new MCvScalar(255, 255, 255), 1, LineType.EightConnected, null);
                    CvInvoke.DrawContours(img_EdgeText, Contours, i, new MCvScalar(255, 255, 255), 1, LineType.EightConnected, null);
                    Rectangle rect = CvInvoke.BoundingRectangle(Contours[i]);
                    CvInvoke.PutText(img_EdgeText, len.ToString("###.#"), new Point(rect.X, rect.Y + rect.Height), Emgu.CV.CvEnum.FontFace.HersheyDuplex, 0.2, new Bgr(Color.Red).MCvScalar);
                    C.Add(Contours[i]);
                }

                try
                {
                    do
                    {
                        Circles = CvInvoke.HoughCircles(img_Edge,           // Input image
                                                        HoughType.Gradient, // Method
                                                        dp,                 //Resolution of the accumulator used to detect centers of the circles
                                                        minDist,            //min distance
                                                        CannyThres,         // Canny high threshold
                                                        HoughThres,         // Hough counting threshold
                                                        minRadius,          //min radius
                                                        maxRadius           //max radius
                                                        );

                        list_Iris = new List <CircleF>();

                        HoughThres -= 5;
                        if (HoughThres <= 0)
                        {
                            Console.WriteLine("cythred=0");
                            //Only save the first 30th  Circles
                            int limit = 0;
                            foreach (CircleF cy in Circles)
                            {
                                list_Iris.Add(cy);
                                limit++;
                                if (limit == 60 || limit > Circles.Length)
                                {
                                    break;
                                }
                            }
                        }
                    } while (list_Iris.Count <= 5);
                }
                catch (Emgu.CV.Util.CvException ex) { Console.WriteLine(ex); }

                // by  gradient
                list_Iris = CircleVerify(list_Iris);
            }
            else
            {
                MessageBox.Show("無法偵測瞳孔,請重新拍攝 \r\n (Contours.size = 0)");
                return(null);
            }

            if (list_Iris.Count != 0)
            {
                this.iris = list_Iris[0];
            }

            return(list_Iris);
        }
Beispiel #18
0
    private void HandleGrab(object sender, EventArgs e)
    {
        Mat image = new Mat();

        if (capture.IsOpened)
        {
            capture.Retrieve(image);
        }
        if (image.IsEmpty)
        {
            return;
        }
        Mat grayImg = image.Clone();

        CvInvoke.CvtColor(image, grayImg, ColorConversion.Bgr2Gray);
        CvInvoke.AdaptiveThreshold(grayImg, grayImg, 255, AdaptiveThresholdType.MeanC, ThresholdType.BinaryInv, 21, 11);

        VectorOfVectorOfPoint contours   = new VectorOfVectorOfPoint();
        VectorOfPoint         approx     = new VectorOfPoint();
        VectorOfVectorOfPoint candidates = new VectorOfVectorOfPoint();
        Mat hierarchy = new Mat();

        CvInvoke.FindContours(grayImg, contours, hierarchy, RetrType.List, ChainApproxMethod.ChainApproxSimple);

        for (int i = 0; i < contours.Size; i++)
        {
            CvInvoke.ApproxPolyDP(contours[i], approx, CvInvoke.ArcLength(contours[i], true) * 0.05, true);
            if (approx.Size == 4)
            {
                if (CvInvoke.ContourArea(contours[i]) > 300)
                {
                    var rect = CvInvoke.BoundingRectangle(approx);
                    if (rect.Height > 0.95 * rect.Width || rect.Height < 0.95 * rect.Width)
                    {
                        candidates.Push(approx);
                        CvInvoke.DrawContours(image, contours, i, new MCvScalar(0, 0, 255), 4);
                        CvInvoke.Rectangle(image, rect, new MCvScalar(0, 255, 0), 3);
                    }
                }
            }
        }

        for (int i = 0; i < candidates.Size; i++)
        {
            System.Drawing.PointF[] pts = new System.Drawing.PointF[4];
            pts[0] = new System.Drawing.PointF(0, 0);
            pts[1] = new System.Drawing.PointF(64 - 1, 0);
            pts[2] = new System.Drawing.PointF(64 - 1, 64 - 1);
            pts[3] = new System.Drawing.PointF(0, 64 - 1);
            VectorOfPointF          perfect    = new VectorOfPointF(pts);
            System.Drawing.PointF[] sample_pts = new System.Drawing.PointF[4];
            for (int j = 0; j < 4; j++)
            {
                sample_pts[j] = new System.Drawing.PointF(candidates[i][j].X, candidates[i][j].Y);
            }
            VectorOfPointF sample = new VectorOfPointF(sample_pts);

            var tf = CvInvoke.GetPerspectiveTransform(sample, perfect);

            Mat warped = new Mat();
            CvInvoke.WarpPerspective(image, warped, tf, new System.Drawing.Size(64, 64));

            CvInvoke.Imshow("Warped " + i, warped);
        }

        CvInvoke.Imshow("Original", image);
        CvInvoke.Imshow("Gray", grayImg);
    }
        public List <List <string> > GetComments(string namePDF, Mat _frame)
        {
            List <List <string> > comments     = new List <List <string> >();
            List <String>         aux_comments = new List <string>();

            Image <Bgr, byte> imagen_aux = _frame.ToImage <Bgr, byte>();

            imagen_aux = imagen_aux.Rotate(180, new Bgr(0, 0, 0));
            Mat m                 = new Mat();
            Mat n                 = new Mat();
            Mat o                 = new Mat();
            Mat aux               = new Mat();
            Mat binaryDiffFrame   = new Mat();
            Mat denoisedDiffFrame = new Mat();
            Mat finalFrame        = new Mat();


            //Obtener directorio
            directorio = Directory.GetCurrentDirectory();
            Console.WriteLine(directorio);

            //Cantidad de comentarios
            cantComentarios = 0;

            //
            //OBTENER COLOR
            //
            Image <Bgr, Byte> imge           = _frame.ToImage <Bgr, Byte>();
            Image <Bgr, byte> ret            = imge.Copy();
            Image <Bgr, byte> auxImge        = imge.Copy();
            Image <Bgr, byte> auxImge2       = imge.Copy();
            Image <Bgr, byte> auxImge3       = imge.Copy();
            Image <Bgr, byte> resultadoFinal = imge.Copy();
            //Transformar a espacio de color HSV
            Image <Hsv, Byte> hsvimg = auxImge.Convert <Hsv, Byte>();

            //extract the hue and value channels
            Image <Gray, Byte>[] channels = hsvimg.Split();  //separar en componentes
            Image <Gray, Byte>   imghue   = channels[0];     //hsv, channels[0] es hue.
            Image <Gray, Byte>   imgval   = channels[2];     //hsv, channels[2] es value.

            //Filtro amarillo
            //140 en adelante //30
            Image <Gray, byte> huefilter = imghue.InRange(new Gray(0), new Gray(30));
            //Filtro colores menos brillantes
            Image <Gray, byte> valfilter = imgval.InRange(new Gray(100), new Gray(255));

            //Filtro de saturación - quitar blancos
            channels[1]._ThresholdBinary(new Gray(10), new Gray(255)); // Saturacion

            //Unir los filtros para obtener la imagen
            Image <Gray, byte> colordetimg = huefilter.And(valfilter).And(channels[1]);//aqui habia un Not()

            //Colorear imagen

            var mat = auxImge2.Mat;

            mat.SetTo(new MCvScalar(0, 0, 255), colordetimg);
            mat.CopyTo(ret);
            //Image<Bgr, byte> imgout = ret.CopyBlank();//imagen sin fondo negro

            ret._Or(auxImge2);
            //Muestra imagen con color destacado

            Mat SE2 = CvInvoke.GetStructuringElement(Emgu.CV.CvEnum.ElementShape.Rectangle, new Size(3, 2), new Point(-1, -1));

            CvInvoke.MorphologyEx(colordetimg, colordetimg, MorphOp.Erode, SE2, new Point(-1, -1), 3, BorderType.Default, new MCvScalar(255));
            Mat SE3 = CvInvoke.GetStructuringElement(Emgu.CV.CvEnum.ElementShape.Rectangle, new Size(3, 2), new Point(-1, -1));

            CvInvoke.MorphologyEx(colordetimg, colordetimg, MorphOp.Dilate, SE3, new Point(-1, -1), 4, BorderType.Default, new MCvScalar(255));


            Mat SE = CvInvoke.GetStructuringElement(Emgu.CV.CvEnum.ElementShape.Rectangle, new Size(3, 3), new Point(-1, -1));

            CvInvoke.MorphologyEx(colordetimg, aux, Emgu.CV.CvEnum.MorphOp.Close, SE, new Point(-1, -1), 5, Emgu.CV.CvEnum.BorderType.Reflect, new MCvScalar(255));


            Image <Bgr, byte> temp = aux.ToImage <Bgr, byte>();
            var temp2 = temp.SmoothGaussian(5).Convert <Gray, byte>().ThresholdBinary(new Gray(230), new Gray(255));
            VectorOfVectorOfPoint contorno = new VectorOfVectorOfPoint();
            Mat matAux = new Mat();

            CvInvoke.FindContours(temp2, contorno, matAux, Emgu.CV.CvEnum.RetrType.External, Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple);
            for (int i = 0; i < contorno.Size; i++)
            {
                VectorOfPoint approxContour = new VectorOfPoint();
                double        perimetro     = CvInvoke.ArcLength(contorno[i], true);
                VectorOfPoint approx        = new VectorOfPoint();
                double        area          = CvInvoke.ContourArea(contorno[i]);

                if (area > 15000)
                {
                    var moments = CvInvoke.Moments(contorno[i]);
                    int x       = (int)(moments.M10 / moments.M00);
                    int y       = (int)(moments.M01 / moments.M00);
                    CvInvoke.ApproxPolyDP(contorno[i], approx, 0.04 * perimetro, true);

                    if (approx.Size == 4) //The contour has 4 vertices.
                    {
                        cantComentarios = cantComentarios + 1;
                        CvInvoke.DrawContours(resultadoFinal, contorno, i, new MCvScalar(0, 255, 255), 2);
                        RotatedRect rectangle = CvInvoke.MinAreaRect(approx);
                        //CvInvoke.DrawContours(resultadoFinal, contorno, i, new MCvScalar(255, 255, 255), 2, LineType.AntiAlias);
                        resultadoFinal.Draw(rectangle, new Bgr(Color.Cyan), 1);
                        CvInvoke.PutText(resultadoFinal, "Comentario", new Point(x, y),
                                         Emgu.CV.CvEnum.FontFace.HersheySimplex, 0.5, new MCvScalar(0, 255, 255), 2);
                        System.Drawing.Point[]   pts = approx.ToArray();
                        System.Drawing.Rectangle box = new System.Drawing.Rectangle();
                        box = CvInvoke.BoundingRectangle(approx);


                        coorComentario.Add(new Point(box.X, box.Y));
                        auxImge3.ROI = box;
                        final        = auxImge3.Copy();
                        //Bitmap src = bmp;
                        final = final.Rotate(180, new Bgr(0, 0, 0));
                        final.Save("comment" + cantComentarios + ".jpg");

                        Image <Gray, Byte> finalGray = final.Convert <Gray, Byte>();
                        CvInvoke.cvResetImageROI(auxImge3);
                        //El parámetro blockSize es el tamaño de la vecindad, y el valor de los píxeles procesados ​​debe ser mayor que el valor de vecindad promedio menos param1
                        CvInvoke.AdaptiveThreshold(finalGray, finalGray, 255, AdaptiveThresholdType.MeanC, ThresholdType.Binary, 31, 20);
                    }
                }
            }
            Console.WriteLine("cantidad de comentarios " + cantComentarios);
            if (cantComentarios > 0)
            {
                aux_comments.Add("SI");
                comments.Add(aux_comments);
                SaveComments(namePDF);
            }

            else
            {
                aux_comments.Add("NO");
                comments.Add(aux_comments);
            }

            return(comments);
        }
            /// <summary>

            /// Determina si un contorno es un circulo, verificando que tenga al menos 7 puntos y todos estén al mismo radio del centro

            /// </summary>

            /// <param name="MaxVariation"> Máxima desviacion permitida (0 a 1) </param>

            /// <returns></returns>

            public static bool isCircle(this VectorOfPoint contour, float MaxVariation = 0.2f)
            {
                bool result = false;



                if (contour.Size >= 7)
                {
                    Moments Moments = CvInvoke.Moments(contour);

                    Vector2 Center = Vector2.zero;

                    Center.x = (float)(Moments.M10 / Moments.M00);

                    Center.y = (float)(Moments.M01 / Moments.M00);



                    result = true;

                    Vector2[] pts = contour.ToVector2();

                    float MaxRadius = (pts[0] - Center).magnitude;

                    float MinRadius = MaxRadius;

                    float MinLimit = 1 - MaxVariation;

                    float MaxLimit = 1 + MaxVariation;



                    //Verifica que el radio sea consistente

                    for (int j = 1; j < pts.Length; j++)
                    {
                        float r = (pts[j] - Center).magnitude;

                        if (r > MaxRadius)
                        {
                            MaxRadius = r;
                        }

                        if (r < MinRadius)
                        {
                            MinRadius = r;
                        }
                    }



                    if (MinRadius / MaxRadius < MinLimit)
                    {
                        result = false;
                    }



                    //Verifica que el perímetro sea consistente

                    if (result)
                    {
                        double perimetroReal = CvInvoke.ArcLength(contour, true);

                        float Radio = (MaxRadius + MinRadius) * 0.5f;

                        float perimetroIdeal = 6.28f * Radio;

                        float factor = (float)(perimetroIdeal / perimetroReal);

                        if ((factor < MinLimit) || (factor > MaxLimit))
                        {
                            result = false;
                        }
                    }



                    pts = null;
                }



                return(result);
            }
        private MovesDetectionResult DetectMoves(CamService cam)
        {
            var maxDartContourArc   = configService.MaxContourArcValue * 1.5;
            var maxDartContourArea  = configService.MaxContourAreaValue * 1.5;
            var maxDartContourWidth = configService.MaxContourWidthValue * 1.5;

            var minDartContourArc   = configService.MinContourArcValue;
            var minDartContourArea  = configService.MinContourAreaValue;
            var minDartContourWidth = configService.MinContourWidthValue;

            var allContours = new VectorOfVectorOfPoint();

            CvInvoke.FindContours(cam.ThrowExtractedRoiFrame,
                                  allContours,
                                  new Mat(),
                                  RetrType.External,
                                  ChainApproxMethod.ChainApproxNone);

            if (!detectionEnabled || allContours.Size == 0)
            {
                return(MovesDetectionResult.Nothing);
            }

            var contourWithMaxArc   = new VectorOfPoint();
            var contourWithMaxArea  = new VectorOfPoint();
            var contourWithMaxWidth = new VectorOfPoint();

            var maxArс   = 0.0;
            var maxArea  = 0.0;
            var maxWidth = 0.0;

            for (var i = 0; i < allContours.Size; i++)
            {
                var tempContour = allContours[i];

                var tempContourArс = CvInvoke.ArcLength(tempContour, true);
                if (tempContourArс > maxArс)
                {
                    maxArс            = tempContourArс;
                    contourWithMaxArc = tempContour;
                }

                var tempContourArea = CvInvoke.ContourArea(tempContour);
                if (tempContourArea > maxArea)
                {
                    maxArea            = tempContourArea;
                    contourWithMaxArea = tempContour;
                }

                var rect             = CvInvoke.MinAreaRect(tempContour);
                var box              = CvInvoke.BoxPoints(rect);
                var contourBoxPoint1 = new PointF(box[0].X, (float)cam.roiPosYSlider + box[0].Y);
                var contourBoxPoint2 = new PointF(box[1].X, (float)cam.roiPosYSlider + box[1].Y);
                var contourBoxPoint4 = new PointF(box[3].X, (float)cam.roiPosYSlider + box[3].Y);
                var side1            = MeasureService.FindDistance(contourBoxPoint1, contourBoxPoint2);
                var side2            = MeasureService.FindDistance(contourBoxPoint4, contourBoxPoint1);
                var tempContourWidth = side1 < side2
                                           ? side1
                                           : side2;
                if (tempContourWidth > maxWidth)
                {
                    maxWidth            = tempContourWidth;
                    contourWithMaxWidth = tempContour;
                }
            }

            if (workingMode == DetectionServiceWorkingMode.Crossing ||
                maxArс >= minDartContourArc &&
                maxArс <= maxDartContourArc &&
                maxArea >= minDartContourArea &&
                maxArea <= maxDartContourArea &&
                maxWidth >= minDartContourWidth &&
                maxWidth <= maxDartContourWidth &&
                contourWithMaxArc.Equals(contourWithMaxArea) &&
                contourWithMaxArea.Equals(contourWithMaxWidth) &&
                contourWithMaxWidth.Equals(contourWithMaxArc)
                )
            {
                return(MovesDetectionResult.Throw);
            }

            if (maxArс > maxDartContourArc ||
                maxArea > maxDartContourArea ||
                maxWidth > maxDartContourWidth)
            {
                return(MovesDetectionResult.Extraction);
            }

            return(MovesDetectionResult.Nothing);
        }
        private void DetectObject(Mat detectionFrame, Mat displayFrame, Rectangle box)
        {
            Image <Bgr, Byte> buffer_im = displayFrame.ToImage <Bgr, Byte>();

            using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
            {
                VectorOfPoint biggestContour = null;
                IOutputArray  hirarchy       = null;

                CvInvoke.FindContours(detectionFrame, contours, hirarchy, RetrType.List, ChainApproxMethod.ChainApproxSimple);


                if (contours.Size > 0)
                {
                    double        maxArea = 0;
                    int           chosen  = 0;
                    VectorOfPoint contour = null;
                    for (int i = 0; i < contours.Size; i++)
                    {
                        contour = contours[i];

                        double area = CvInvoke.ContourArea(contour);
                        if (area > maxArea)
                        {
                            maxArea = area;
                            chosen  = i;
                        }
                    }


                    //MarkDetectedObject(displayFrame, contours[chosen], maxArea);//dibuja una envoltura roja

                    VectorOfPoint hullPoints = new VectorOfPoint();
                    VectorOfInt   hullInt    = new VectorOfInt();

                    CvInvoke.ConvexHull(contours[chosen], hullPoints, true);
                    CvInvoke.ConvexHull(contours[chosen], hullInt, false);

                    Mat defects = new Mat();


                    if (hullInt.Size > 3)
                    {
                        CvInvoke.ConvexityDefects(contours[chosen], hullInt, defects);
                    }

                    box = CvInvoke.BoundingRectangle(hullPoints);
                    CvInvoke.Rectangle(displayFrame, box, drawingColor); //Box rectangulo que encierra el area mas grande
                                                                         // cropbox = crop_color_frame(displayFrame, box);

                    buffer_im.ROI = box;

                    Image <Bgr, Byte> cropped_im = buffer_im.Copy();
                    pictureBox8.Image = cropped_im.Bitmap;
                    Point center = new Point(box.X + box.Width / 2, box.Y + box.Height / 2);//centro  rectangulo MOUSE

                    VectorOfPoint start_points = new VectorOfPoint();
                    VectorOfPoint far_points   = new VectorOfPoint();

                    if (!defects.IsEmpty)
                    {
                        Matrix <int> m = new Matrix <int>(defects.Rows, defects.Cols,
                                                          defects.NumberOfChannels);
                        defects.CopyTo(m);
                        int xe = 2000, ye = 2000;
                        int xs = 2000, ys = 2000;
                        int xer = 2000, yer = 2000;
                        int xsr = 2000, ysr = 2000;
                        int xem = 0, yem = 0;
                        int xsm = 0, ysm = 0;
                        int xez = 0, yez = 0;
                        int xsz = 0, ysz = 0;
                        int y = 0, x = 0;
                        int ym = 0, xm = 0;
                        int yr = 0, xr = 0;
                        int yz = 0, xz = 0;
                        for (int i = 0; i < m.Rows; i++)
                        {
                            int   startIdx   = m.Data[i, 0];
                            int   endIdx     = m.Data[i, 1];
                            int   farIdx     = m.Data[i, 2];
                            Point startPoint = contours[chosen][startIdx];
                            Point endPoint   = contours[chosen][endIdx];
                            Point farPoint   = contours[chosen][farIdx];
                            CvInvoke.Circle(displayFrame, endPoint, 3, new MCvScalar(0, 255, 255));
                            CvInvoke.Circle(displayFrame, startPoint, 3, new MCvScalar(255, 255, 0));

                            if (true)
                            {
                                if (endPoint.Y < ye)
                                {
                                    xe = endPoint.X;

                                    ye = endPoint.Y;
                                }

                                if (startPoint.Y < ys)
                                {
                                    xs = startPoint.X;

                                    ys = startPoint.Y;
                                }

                                if (ye < ys)
                                {
                                    y = ye;
                                    x = xe;
                                }
                                else
                                {
                                    y = ys;
                                    x = xs;
                                }


                                if (endPoint.Y > yem)
                                {
                                    xem = endPoint.X;

                                    yem = endPoint.Y;
                                }

                                if (startPoint.Y > ysm)
                                {
                                    xsm = startPoint.X;

                                    ysm = startPoint.Y;
                                }

                                if (yem > ysm)
                                {
                                    ym = yem;
                                    xm = xem;
                                }
                                else
                                {
                                    y = ys;
                                    x = xs;
                                }

                                if (endPoint.X < xer)
                                {
                                    xer = endPoint.X;

                                    yer = endPoint.Y;
                                }

                                if (startPoint.X < xsr)
                                {
                                    xsr = startPoint.X;

                                    ysr = startPoint.Y;
                                }

                                if (xer < xsr)
                                {
                                    yr = yer;
                                    xr = xer;
                                }
                                else
                                {
                                    yr = ysr;
                                    xr = xsr;
                                }


                                if (endPoint.X > xez)
                                {
                                    xez = endPoint.X;

                                    yez = endPoint.Y;
                                }

                                if (startPoint.X > xsz)
                                {
                                    xsz = startPoint.X;

                                    ysz = startPoint.Y;
                                }

                                if (xez > xsz)
                                {
                                    yz = yez;
                                    xz = xez;
                                }

                                else
                                {
                                    yz = ysz;
                                    xz = xsz;
                                }
                            }

                            /*var info = new string[] {
                             *
                             * $"Posicion: {endPoint.X}, {endPoint.Y}"
                             * };
                             *
                             * WriteMultilineText(displayFrame, info, new Point(endPoint.X + 5, endPoint.Y));*/

                            double distance = Math.Round(Math.Sqrt(Math.Pow((center.X - farPoint.X), 2) + Math.Pow((center.Y - farPoint.Y), 2)), 1);
                            if (distance < box.Height * 0.3)
                            {
                                CvInvoke.Circle(displayFrame, farPoint, 3, new MCvScalar(255, 0, 0));
                            }

                            CvInvoke.Line(displayFrame, startPoint, endPoint, new MCvScalar(0, 255, 0));
                            // CvInvoke.Line(displayFrame, startPoint, farPoint, new MCvScalar(0, 255, 255));
                        }
                        var infoe      = new string[] { $"Punto", $"Posicion: {x}, {y}" };
                        var infos      = new string[] { $"Punto", $"Posicion: {xm}, {ym}" };
                        var infor      = new string[] { $"Punto", $"Posicion: {x}, {y}" };
                        var infoz      = new string[] { $"Punto", $"Posicion: {xm}, {ym}" };
                        var infoCentro = new string[] { $"Centro", $"Posicion: {xm}, {ym}" };

                        var xCentro = (x + xm + xr + xz) / 4;
                        var yCentro = (y + ym + yr + yz) / 4;

                        WriteMultilineText(displayFrame, infoe, new Point(x + 30, y));
                        CvInvoke.Circle(displayFrame, new Point(x, y), 5, new MCvScalar(255, 0, 255), 2);
                        Image <Bgr, byte> temp = detectionFrame.ToImage <Bgr, byte>();
                        var temp2 = temp.SmoothGaussian(5).Convert <Gray, byte>().ThresholdBinary(new Gray(230), new Gray(255));
                        VectorOfVectorOfPoint contorno = new VectorOfVectorOfPoint();
                        Mat mat = new Mat();
                        CvInvoke.FindContours(temp2, contorno, mat, Emgu.CV.CvEnum.RetrType.External, Emgu.CV.CvEnum.ChainApproxMethod.LinkRuns);
                        for (int i = 0; i < contorno.Size; i++)
                        {
                            double        perimetro = CvInvoke.ArcLength(contorno[i], true);
                            VectorOfPoint approx    = new VectorOfPoint();
                            CvInvoke.ApproxPolyDP(contorno[i], approx, 0.04 * perimetro, true);
                            CvInvoke.DrawContours(displayFrame, contorno, i, new MCvScalar(0, 255, 255), 2);
                        }

                        WriteMultilineText(displayFrame, infos, new Point(xm + 30, ym));
                        CvInvoke.Circle(displayFrame, new Point(xm, ym), 5, new MCvScalar(255, 0, 255), 2);
                        WriteMultilineText(displayFrame, infor, new Point(xr + 30, yr));
                        CvInvoke.Circle(displayFrame, new Point(xr, yr), 5, new MCvScalar(255, 0, 255), 2);
                        WriteMultilineText(displayFrame, infoz, new Point(xz + 30, yz));
                        CvInvoke.Circle(displayFrame, new Point(xz, yz), 5, new MCvScalar(255, 0, 255), 2);

                        WriteMultilineText(displayFrame, infoz, new Point(xCentro + 30, yCentro));
                        CvInvoke.Circle(displayFrame, new Point(xCentro, yCentro), 2, new MCvScalar(0, 100, 0), 4);
                        //CvInvoke.Circle(picture, new Point(x * 2, y * 4), 20, new MCvScalar(255, 0, 255), 2);*/
                    }
                }
            }
        }
Beispiel #23
0
        public Mat ProcessImage(Mat img)
        {
            using (UMat gray = new UMat())
                using (UMat cannyEdges = new UMat())
                    using (Mat triangleRectangleImage = new Mat(img.Size, DepthType.Cv8U, 3)) //image to draw triangles and rectangles on
                        using (Mat circleImage = new Mat(img.Size, DepthType.Cv8U, 3))        //image to draw circles on
                            using (Mat lineImage = new Mat(img.Size, DepthType.Cv8U, 3))      //image to drtaw lines on
                            {
                                //Convert the image to grayscale and filter out the noise
                                CvInvoke.CvtColor(img, gray, ColorConversion.Bgr2Gray);

                                //Remove noise
                                CvInvoke.GaussianBlur(gray, gray, new Size(3, 3), 1);

                                #region circle detection
                                double    cannyThreshold             = 180.0;
                                double    circleAccumulatorThreshold = 120;
                                CircleF[] circles = CvInvoke.HoughCircles(gray, HoughModes.Gradient, 2.0, 20.0, cannyThreshold,
                                                                          circleAccumulatorThreshold, 5);
                                #endregion

                                #region Canny and edge detection
                                double cannyThresholdLinking = 120.0;
                                CvInvoke.Canny(gray, cannyEdges, cannyThreshold, cannyThresholdLinking);
                                LineSegment2D[] lines = CvInvoke.HoughLinesP(
                                    cannyEdges,
                                    1,              //Distance resolution in pixel-related units
                                    Math.PI / 45.0, //Angle resolution measured in radians.
                                    20,             //threshold
                                    30,             //min Line width
                                    10);            //gap between lines
                                #endregion

                                #region Find triangles and rectangles
                                List <Triangle2DF> triangleList = new List <Triangle2DF>();
                                List <RotatedRect> boxList      = new List <RotatedRect>(); //a box is a rotated rectangle
                                using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
                                {
                                    CvInvoke.FindContours(cannyEdges, contours, null, RetrType.List,
                                                          ChainApproxMethod.ChainApproxSimple);
                                    int count = contours.Size;
                                    for (int i = 0; i < count; i++)
                                    {
                                        using (VectorOfPoint contour = contours[i])
                                            using (VectorOfPoint approxContour = new VectorOfPoint())
                                            {
                                                CvInvoke.ApproxPolyDP(contour, approxContour, CvInvoke.ArcLength(contour, true) * 0.05,
                                                                      true);
                                                if (CvInvoke.ContourArea(approxContour, false) > 250
                                                    )                            //only consider contours with area greater than 250
                                                {
                                                    if (approxContour.Size == 3) //The contour has 3 vertices, it is a triangle
                                                    {
                                                        Point[] pts = approxContour.ToArray();
                                                        triangleList.Add(new Triangle2DF(
                                                                             pts[0],
                                                                             pts[1],
                                                                             pts[2]
                                                                             ));
                                                    }
                                                    else if (approxContour.Size == 4) //The contour has 4 vertices.
                                                    {
                                                        #region determine if all the angles in the contour are within [80, 100] degree
                                                        bool            isRectangle = true;
                                                        Point[]         pts         = approxContour.ToArray();
                                                        LineSegment2D[] edges       = PointCollection.PolyLine(pts, true);

                                                        for (int j = 0; j < edges.Length; j++)
                                                        {
                                                            double angle = Math.Abs(
                                                                edges[(j + 1) % edges.Length].GetExteriorAngleDegree(edges[j]));
                                                            if (angle < 80 || angle > 100)
                                                            {
                                                                isRectangle = false;
                                                                break;
                                                            }
                                                        }

                                                        #endregion

                                                        if (isRectangle)
                                                        {
                                                            boxList.Add(CvInvoke.MinAreaRect(approxContour));
                                                        }
                                                    }
                                                }
                                            }
                                    }
                                }
                                #endregion

                                #region draw triangles and rectangles
                                triangleRectangleImage.SetTo(new MCvScalar(0));
                                foreach (Triangle2DF triangle in triangleList)
                                {
                                    CvInvoke.Polylines(triangleRectangleImage, Array.ConvertAll(triangle.GetVertices(), Point.Round),
                                                       true, new Bgr(Color.DarkBlue).MCvScalar, 2);
                                }

                                foreach (RotatedRect box in boxList)
                                {
                                    CvInvoke.Polylines(triangleRectangleImage, Array.ConvertAll(box.GetVertices(), Point.Round), true,
                                                       new Bgr(Color.DarkOrange).MCvScalar, 2);
                                }

                                //Drawing a light gray frame around the image
                                CvInvoke.Rectangle(triangleRectangleImage,
                                                   new Rectangle(Point.Empty,
                                                                 new Size(triangleRectangleImage.Width - 1, triangleRectangleImage.Height - 1)),
                                                   new MCvScalar(120, 120, 120));
                                //Draw the labels
                                CvInvoke.PutText(triangleRectangleImage, "Triangles and Rectangles", new Point(20, 20),
                                                 FontFace.HersheyDuplex, 0.5, new MCvScalar(120, 120, 120));
                                #endregion

                                #region draw circles
                                circleImage.SetTo(new MCvScalar(0));
                                foreach (CircleF circle in circles)
                                {
                                    CvInvoke.Circle(circleImage, Point.Round(circle.Center), (int)circle.Radius,
                                                    new Bgr(Color.Brown).MCvScalar, 2);
                                }

                                //Drawing a light gray frame around the image
                                CvInvoke.Rectangle(circleImage,
                                                   new Rectangle(Point.Empty, new Size(circleImage.Width - 1, circleImage.Height - 1)),
                                                   new MCvScalar(120, 120, 120));
                                //Draw the labels
                                CvInvoke.PutText(circleImage, "Circles", new Point(20, 20), FontFace.HersheyDuplex, 0.5,
                                                 new MCvScalar(120, 120, 120));
                                #endregion

                                #region draw lines
                                lineImage.SetTo(new MCvScalar(0));
                                foreach (LineSegment2D line in lines)
                                {
                                    CvInvoke.Line(lineImage, line.P1, line.P2, new Bgr(Color.Green).MCvScalar, 2);
                                }
                                //Drawing a light gray frame around the image
                                CvInvoke.Rectangle(lineImage,
                                                   new Rectangle(Point.Empty, new Size(lineImage.Width - 1, lineImage.Height - 1)),
                                                   new MCvScalar(120, 120, 120));
                                //Draw the labels
                                CvInvoke.PutText(lineImage, "Lines", new Point(20, 20), FontFace.HersheyDuplex, 0.5,
                                                 new MCvScalar(120, 120, 120));
                                #endregion

                                Mat result = new Mat();
                                CvInvoke.VConcat(new Mat[] { img, triangleRectangleImage, circleImage, lineImage }, result);
                                return(result);
                            }
        }
Beispiel #24
0
        private void wykryjZnaki()
        {
            //lista trójkątów
            List <Triangle2DF> triangleList = new List <Triangle2DF>();

            //lista prostokątów i kwadratów
            List <RotatedRect> boxList = new List <RotatedRect>();

            zwiekszProgressBar(1);

            //przetworzenie zdjecia do postaci wskazujacej tylko biale kontury na czarnym tle
            Image <Gray, byte> canny_zdj = new Image <Gray, byte>(imgInput.Width, imgInput.Height, new Gray(0));

            canny_zdj = imgInput.Canny(300, 250);

            //przypisanie canny_zdj do pictureBox i rozciagniecie
            zdjecieCannyBox.Image    = canny_zdj.Bitmap;
            zdjecieCannyBox.SizeMode = PictureBoxSizeMode.StretchImage;
            zwiekszProgressBar(2);

            LineSegment2D[] lines = CvInvoke.HoughLinesP(
                canny_zdj,
                1,
                Math.PI / 45.0,
                20,
                30,
                10);

            Image <Gray, byte>    imgOut   = canny_zdj.Convert <Gray, byte>().ThresholdBinary(new Gray(50), new Gray(200));
            VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
            Mat hier = new Mat();

            zwiekszProgressBar(1);

            //wygladzenie obrazu
            imgSmooth = imgInput.PyrDown().PyrUp();
            imgSmooth._SmoothGaussian(3);

            //ograniczenie wykrywanych figur do odpowiedniego zakresu ze skali RGB - zoltego
            imgOut = imgSmooth.InRange(new Bgr(0, 140, 150), new Bgr(80, 255, 255));
            imgOut = imgOut.PyrDown().PyrUp();
            imgOut._SmoothGaussian(3);

            zwiekszProgressBar(2);

            Dictionary <int, double> dict = new Dictionary <int, double>();

            //wyszukanie konturow spelniajacych wymogi odnosnie mi.in. koloru
            CvInvoke.FindContours(imgOut, contours, null, Emgu.CV.CvEnum.RetrType.List, Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple);
            label1.Text = contours.Size.ToString();

            //jesli odnaleziono chocby jeden kontur
            if (contours.Size > 0)
            {
                //petla przechodzaca po wszystkich wykrytych konturach
                for (int i = 0; i < contours.Size; i++)
                {
                    using (VectorOfPoint contour = contours[i])
                        using (VectorOfPoint approxContour = new VectorOfPoint())
                        {
                            CvInvoke.ApproxPolyDP(contour, approxContour, CvInvoke.ArcLength(contour, true) * 0.05, true);

                            //filtr wielkosci pola wykrytego konturu
                            if (CvInvoke.ContourArea(approxContour, false) > 50)
                            {
                                //jesli to trójkąt
                                if (approxContour.Size == 3)
                                {
                                    //tablica punktow i dodanie ich do tablicy trojkatow
                                    Point[] pts = approxContour.ToArray();
                                    triangleList.Add(new Triangle2DF(
                                                         pts[0],
                                                         pts[1],
                                                         pts[2]
                                                         ));

                                    //sprawdzenie czy wykryty trojkat jest figura obróconą jednym z wierzcholkow do dolu
                                    if (pts[1].X > pts[0].X && pts[1].Y > pts[0].Y)
                                    {
                                        //ustawienie znaku A-7
                                        ustawWykrytyZnak(2);
                                        double area = CvInvoke.ContourArea(contours[i]);
                                        //dodanie do tablicy glownej
                                        dict.Add(i, area);
                                    }
                                }

                                //jesli to czworokat
                                else if (approxContour.Size == 4)
                                {
                                    bool isRectangle = true;

                                    ///rozbicie figury na pojedyncze krawedzie
                                    Point[]         pts   = approxContour.ToArray();
                                    LineSegment2D[] edges = PointCollection.PolyLine(pts, true);

                                    //petla przechodzaca po wszystkich krawedziach
                                    for (int j = 0; j < edges.Length; j++)
                                    {
                                        //sprawdzenie wielkosci kąta miedzy sprawdzanymi krawedziami
                                        double angle = Math.Abs(
                                            edges[(j + 1) % edges.Length].GetExteriorAngleDegree(edges[j]));
                                        //przerwanie jesli kąty w figurze są mniejsze niż 80 i wieksze niż 100
                                        if (angle < 80 || angle > 100)
                                        {
                                            isRectangle = false;
                                            break;
                                        }
                                    }
                                    if (isRectangle)
                                    {
                                        RotatedRect rrect = CvInvoke.MinAreaRect(contours[i]);

                                        //ostateczne sprawdzenie czy wykryta figura jest obrocona wzgledem srodka o wartosc od 40 do 50
                                        //stopni - znak D-1 jest obroconym kwadratem o 45 st wzgledem srodka
                                        if ((rrect.Angle < -40 && rrect.Angle > -50) || (rrect.Angle > 40 && rrect.Angle < 50))
                                        {
                                            boxList.Add(CvInvoke.MinAreaRect(approxContour));
                                            double area = CvInvoke.ContourArea(contours[i]);
                                            dict.Add(i, area);
                                            ustawWykrytyZnak(1);
                                        }
                                    }
                                }
                            }
                        }
                }
            }
            zwiekszProgressBar(2);

            var item = dict.OrderByDescending(v => v.Value);

            foreach (var it in item)
            {
                int key = int.Parse(it.Key.ToString());

                //pobranie odpowiednich konturow
                Rectangle rect = CvInvoke.BoundingRectangle(contours[key]);

                //narysowanie czerwonego prostokata wokol wykrytego znaku
                CvInvoke.Rectangle(imgInput, rect, new MCvScalar(0, 0, 255), 1);
            }

            zwiekszProgressBar(2);
            pictureBox2.Image    = imgInput.Bitmap;
            pictureBox2.SizeMode = PictureBoxSizeMode.StretchImage;

            //utworzenie zdjecia wskazujacego WSZYSTKIE kontury w poczatkowym zdjeciu - czerowne linie
            Image <Bgr, Byte> lineImage = imgInput.CopyBlank();

            foreach (LineSegment2D line in lines)
            {
                lineImage.Draw(line, new Bgr(Color.Red), 1);
            }
            zdjecieWykrytyZnak.Image    = lineImage.Bitmap;
            zdjecieWykrytyZnak.SizeMode = PictureBoxSizeMode.StretchImage;
        }
Beispiel #25
0
        public static Bitmap ExtractDocumentFromBitmap(Bitmap bitmap)
        {
            if (bitmap.Width > bitmap.Height)
            {
                bitmap.RotateFlip(RotateFlipType.Rotate90FlipNone);
            }
            using (var image = new Image <Bgr, byte>(bitmap))
                using (var imageGray = image.Convert <Gray, byte>())
                    using (var filteredImage = new Image <Bgr, byte>(bitmap))
                        using (var cannyEdges = new UMat())
                            using (var contours = new VectorOfVectorOfPoint())
                            {
                                CvInvoke.BilateralFilter(imageGray, filteredImage, 9, 75, 75);
                                CvInvoke.AdaptiveThreshold(filteredImage, filteredImage, 255, AdaptiveThresholdType.GaussianC, ThresholdType.Binary, 115, 4);
                                CvInvoke.MedianBlur(filteredImage, filteredImage, 11);
                                CvInvoke.CopyMakeBorder(filteredImage, filteredImage, 5, 5, 5, 5, BorderType.Constant, new MCvScalar(0, 0, 0));
                                CvInvoke.Canny(filteredImage, cannyEdges, 200, 250);
                                CvInvoke.FindContours(cannyEdges, contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple);

                                var    cannyEdgesHeight = cannyEdges.Bitmap.Height;
                                var    cannyEdgesWidth  = cannyEdges.Bitmap.Width;
                                var    areaContour      = (cannyEdgesHeight - 10) * (cannyEdgesWidth - 10);
                                var    areaCount        = areaContour * 0.5;
                                double areaContour2;

                                var sourcePointsVector = new VectorOfPoint();
                                for (int i = 0; i < contours.Size; i++)
                                {
                                    using (var cont = contours[i])
                                    {
                                        CvInvoke.ApproxPolyDP(cont, cont, CvInvoke.ArcLength(cont, true) * 0.05, true);
                                        if (cont.Size == 4 && CvInvoke.IsContourConvex(cont) &&
                                            areaCount < CvInvoke.ContourArea(cont) &&
                                            CvInvoke.ContourArea(cont) < areaContour)
                                        {
                                            sourcePointsVector = cont;
                                            areaContour2       = CvInvoke.ContourArea(cont);
                                            sortVector(sourcePointsVector);
                                            break;
                                        }
                                    }
                                }
                                var sortedVector     = sortVector(sourcePointsVector);
                                var vectorWithOffset = addOffsetToVector(sourcePointsVector, -5);

                                var euclideanHeight = new int[] { getEuclideanDistance(vectorWithOffset[0], vectorWithOffset[1]), getEuclideanDistance(vectorWithOffset[2], vectorWithOffset[3]) }.Max();
                                var euclideanWidth = new int[] { getEuclideanDistance(vectorWithOffset[0], vectorWithOffset[2]), getEuclideanDistance(vectorWithOffset[1], vectorWithOffset[3]) }.Max();

                                VectorOfPoint targetPoints = new VectorOfPoint(new Point[]
                                {
                                    new Point(0, 0),
                                    new Point(0, euclideanWidth),
                                    new Point(euclideanHeight, euclideanWidth),
                                    new Point(euclideanHeight, 0)
                                }.ToArray());

                                var source = sortVector(vectorWithOffset).ToArray().Select(x => new PointF(x.X, x.Y)).ToArray();
                                var target = sortVector(targetPoints).ToArray().Select(x => new PointF(x.X, x.Y)).ToArray();
                                var tran   = CvInvoke.GetPerspectiveTransform(source, target);
                                CvInvoke.WarpPerspective(image, image, tran, new Size(euclideanHeight, euclideanWidth));

                                return(image.ToBitmap((int)standardDocumentWidth * 4, (int)standardDocumentHeight * 4));
                            }
        }
        public static Bitmap PerformShapeDetection(Bitmap frame, ShapeDetectionVariables detectionVars)
        {
            StringBuilder msgBuilder = new StringBuilder("Performance: ");

            Image <Bgr, Byte> img = new Image <Bgr, byte>(frame);
            Mat MatImg            = img.Mat;

            Mat outputImg = new Mat();

            if (CudaInvoke.HasCuda)
            {
                using (GpuMat gMatSrc = new GpuMat())
                    using (GpuMat gMatDst = new GpuMat()) {
                        gMatSrc.Upload(MatImg);
                        CudaGaussianFilter noiseReducetion = new CudaGaussianFilter(MatImg.Depth, img.NumberOfChannels, MatImg.Depth, img.NumberOfChannels, new Size(1, 1), 0);
                        noiseReducetion.Apply(gMatSrc, gMatDst);
                        gMatDst.Download(outputImg);
                    }
            }
            else
            {
                Mat pyrDown = new Mat();
                CvInvoke.PyrDown(img, pyrDown);
                CvInvoke.PyrUp(pyrDown, img);
                outputImg = img.Mat;
            }

            UMat uimage = new UMat();

            CvInvoke.CvtColor(outputImg, uimage, ColorConversion.Bgr2Gray);

            CircleF[] circles = new CircleF[0];
            if (detectionVars.calcCircles)
            {
                circles = CvInvoke.HoughCircles(
                    uimage,
                    HoughType.Gradient, 1.0, 20.0,
                    detectionVars.circleCannyThreshold,
                    detectionVars.circleAccumulatorThreshold == 0 ? 1 : detectionVars.circleAccumulatorThreshold,
                    detectionVars.minradius,
                    detectionVars.maxRadius);
            }

            #region Canny and edge detection
            UMat cannyEdges = new UMat();
            CvInvoke.Canny(uimage, cannyEdges, detectionVars.lineCannyThreshold, detectionVars.cannyThresholdLinking);

            LineSegment2D[] lines = new LineSegment2D[0];
            if (detectionVars.calcLines)
            {
                lines = CvInvoke.HoughLinesP(
                    cannyEdges,
                    1,                           //Distance resolution in pixel-related units
                    Math.PI / 45.0,              //Angle resolution measured in radians.
                    detectionVars.lineThreshold, //threshold
                    detectionVars.minLineWidth,  //min Line width
                    10);                         //gap between lines
            }
            #endregion

            #region Find triangles and rectangles

            List <RotatedRect> boxList = new List <RotatedRect>(); //a box is a rotated rectangle

            if (detectionVars.calcRectTri)
            {
                using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint()) {
                    CvInvoke.FindContours(cannyEdges, contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple);
                    int count = contours.Size;
                    for (int i = 0; i < count; i++)
                    {
                        using (VectorOfPoint contour = contours[i])
                            using (VectorOfPoint approxContour = new VectorOfPoint()) {
                                CvInvoke.ApproxPolyDP(contour, approxContour, CvInvoke.ArcLength(contour, true) * 0.05, true);
                                if (CvInvoke.ContourArea(approxContour, false) > 250)   //only consider contours with area greater than 250
                                {
                                    if (approxContour.Size == 4)                        //The contour has 4 vertices.
                                    {
                                        #region determine if all the angles in the contour are within [80, 100] degree
                                        bool            isRectangle = true;
                                        Point[]         pts         = approxContour.ToArray();
                                        LineSegment2D[] edges       = PointCollection.PolyLine(pts, true);

                                        for (int j = 0; j < edges.Length; j++)
                                        {
                                            double angle = Math.Abs(
                                                edges[(j + 1) % edges.Length].GetExteriorAngleDegree(edges[j]));
                                            if (angle < 80 || angle > 100)
                                            {
                                                isRectangle = false;
                                                break;
                                            }
                                        }
                                        #endregion

                                        if (isRectangle)
                                        {
                                            boxList.Add(CvInvoke.MinAreaRect(approxContour));
                                        }
                                    }
                                }
                            }
                    }
                }
            }

            #endregion

            Image <Bgra, Byte> alphaImgShape = new Image <Bgra, byte>(img.Size.Width, img.Size.Height, new Bgra(0, 0, 0, .5));
            Mat alphaimg = new Mat();
            CvInvoke.CvtColor(img, alphaimg, ColorConversion.Bgr2Bgra);
            #region draw rectangles and triangles
            if (detectionVars.calcRectTri)
            {
                Image <Bgr, Byte> triangleRectangleImage = new Image <Bgr, Byte>(img.Size);

                foreach (RotatedRect box in boxList)
                {
                    CvInvoke.Polylines(triangleRectangleImage, Array.ConvertAll(box.GetVertices(), Point.Round), true, new Bgr(0, 255, 0).MCvScalar, 2);
                }

                CvInvoke.AddWeighted(alphaImgShape, .5, BlackTransparent(triangleRectangleImage), .5, 0, alphaImgShape);


                if (CudaInvoke.HasCuda)
                {
                    using (GpuMat gMatSrc = new GpuMat())
                        using (GpuMat gMatSrc2 = new GpuMat())
                            using (GpuMat gMatDst = new GpuMat()) {
                                gMatSrc.Upload(alphaimg);
                                gMatSrc2.Upload(alphaImgShape);
                                CudaInvoke.AlphaComp(gMatSrc, gMatSrc2, gMatDst, AlphaCompTypes.Plus);
                                gMatDst.Download(alphaimg);
                            }
                }
                else
                {
                    img = Overlay(img, alphaImgShape);
                }
            }
            #endregion

            #region draw circles
            if (detectionVars.calcCircles)
            {
                Image <Bgr, Byte> circleImage = new Image <Bgr, Byte>(img.Size);
                foreach (CircleF circle in circles.Take(10))
                {
                    CvInvoke.Circle(circleImage, Point.Round(circle.Center), (int)circle.Radius, new Bgr(0, 255, 0).MCvScalar, 2);
                }

                alphaImgShape = new Image <Bgra, byte>(img.Size.Width, img.Size.Height, new Bgra(0, 0, 0, .5));
                CvInvoke.AddWeighted(alphaImgShape, .7, BlackTransparent(circleImage), .5, 0, alphaImgShape);
                if (CudaInvoke.HasCuda)
                {
                    using (GpuMat gMatSrc = new GpuMat())
                        using (GpuMat gMatSrc2 = new GpuMat())
                            using (GpuMat gMatDst = new GpuMat()) {
                                gMatSrc.Upload(alphaimg);
                                gMatSrc2.Upload(alphaImgShape);
                                CudaInvoke.AlphaComp(gMatSrc, gMatSrc2, gMatDst, AlphaCompTypes.Plus);
                                gMatDst.Download(alphaimg);
                            }
                }
                else
                {
                    img = Overlay(img, alphaImgShape);
                }
            }
            #endregion

            #region draw lines

            if (detectionVars.calcLines)
            {
                Image <Bgr, Byte> lineImage = new Image <Bgr, Byte>(img.Size);
                foreach (LineSegment2D line in lines)
                {
                    CvInvoke.Line(lineImage, line.P1, line.P2, new Bgr(0, 255, 0).MCvScalar, 2);
                }

                alphaImgShape = new Image <Bgra, byte>(img.Size.Width, img.Size.Height, new Bgra(0, 0, 0, .5));
                CvInvoke.AddWeighted(alphaImgShape, .5, BlackTransparent(lineImage), .5, 0, alphaImgShape);
                if (CudaInvoke.HasCuda)
                {
                    using (GpuMat gMatSrc = new GpuMat())
                        using (GpuMat gMatSrc2 = new GpuMat())
                            using (GpuMat gMatDst = new GpuMat()) {
                                gMatSrc.Upload(alphaimg);
                                gMatSrc2.Upload(alphaImgShape);
                                CudaInvoke.AlphaComp(gMatSrc, gMatSrc2, gMatDst, AlphaCompTypes.Plus);
                                gMatDst.Download(alphaimg);
                            }
                }
                else
                {
                    img = Overlay(img, alphaImgShape);
                }
            }
            #endregion

            GC.Collect();   // first time I've had to use this but this program will use as much memory as possible, resulting in corrptions

            return(alphaimg.Bitmap ?? frame);
        }
Beispiel #27
0
        public Tuple <double, double> contour_1(int min, int max, Image <Bgr, byte> imgInput, int iron_r, int szar_r, int rain_r)
        {
            double carea     = 0;
            double len       = 0;
            double pre_len   = 0;
            double pre_carea = 0;

            // kontur, pole i obwód dla palety barw Iron

            if (iron_r == 1)
            {
                Image <Gray, byte> imgOut = imgInput.Convert <Gray, byte>().InRange(new Gray(min), new Gray(max));

                Emgu.CV.Util.VectorOfVectorOfPoint contours = new Emgu.CV.Util.VectorOfVectorOfPoint();
                Mat hier = new Mat();

                CvInvoke.FindContours(imgOut, contours, hier, Emgu.CV.CvEnum.RetrType.Ccomp, Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple);



                for (int i = 0; i < contours.Size; i++)
                {
                    pre_carea = CvInvoke.ContourArea(contours[i]);

                    carea = carea + pre_carea;

                    pre_len = CvInvoke.ArcLength(contours[i], true);

                    len = len + pre_len;
                }
            }

            // kontur, pole i obwód dla palety barw Rain

            else if (rain_r == 1)
            {
                Image <Gray, byte> imgOut = imgInput.Convert <Gray, byte>().ThresholdBinaryInv(new Gray(min), new Gray(max));



                Emgu.CV.Util.VectorOfVectorOfPoint contours = new Emgu.CV.Util.VectorOfVectorOfPoint();
                Mat hier = new Mat();

                CvInvoke.FindContours(imgOut, contours, hier, Emgu.CV.CvEnum.RetrType.Ccomp, Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple);


                for (int i = 0; i < contours.Size; i++)
                {
                    pre_carea = CvInvoke.ContourArea(contours[i]);

                    carea = carea + pre_carea;

                    pre_len = CvInvoke.ArcLength(contours[i], true);

                    len = len + pre_len;
                }
            }

            // kontur, pole i obwód dla skali szarości
            else if (szar_r == 1)
            {
                Image <Gray, byte>[] channels = imgInput.Split();

                Image <Gray, byte> imgOut = channels[0];


                Image <Gray, byte> imgOut_1 = imgOut.InRange(new Gray(min), new Gray(max));



                Emgu.CV.Util.VectorOfVectorOfPoint contours = new Emgu.CV.Util.VectorOfVectorOfPoint();
                Mat hier = new Mat();

                CvInvoke.FindContours(imgOut_1, contours, hier, Emgu.CV.CvEnum.RetrType.External, Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple);



                for (int i = 0; i < contours.Size; i++)
                {
                    pre_carea = CvInvoke.ContourArea(contours[i]);

                    carea = carea + pre_carea;

                    pre_len = CvInvoke.ArcLength(contours[i], true);

                    len = len + pre_len;
                }
            }


            return(Tuple.Create(carea, len));
        }
Beispiel #28
0
        private void openFileDialog1_FileOk(object sender, CancelEventArgs e)
        {
            outputLabel.Text = "";
            StringBuilder msgBuilder = new StringBuilder("Performance: ");

            Image <Bgr, Byte> img =
                new Image <Bgr, byte>(openFileDialog1.FileName)
                .Resize(400, 400, Emgu.CV.CvEnum.Inter.Linear, true);
            //Convert the image to grayscale and filter out the noise
            UMat uimage = new UMat();

            CvInvoke.CvtColor(img, uimage, ColorConversion.Bgr2Gray);

            //use image pyr to remove noise
            UMat pyrDown = new UMat();

            CvInvoke.PyrDown(uimage, pyrDown);
            CvInvoke.PyrUp(pyrDown, uimage);

            //Image<Gray, Byte> gray = img.Convert<Gray, Byte>().PyrDown().PyrUp();

            #region circle detection
            Stopwatch watch                      = Stopwatch.StartNew();
            double    cannyThreshold             = 80.0;
            double    circleAccumulatorThreshold = 100;
            CircleF[] circles                    = CvInvoke.HoughCircles(uimage, HoughType.Gradient, 2.0, 5.0, cannyThreshold, circleAccumulatorThreshold, 5, 150);
            outputLabel.Text += "C: " + circles.Length;

            watch.Stop();
            msgBuilder.Append(String.Format("Hough circles - {0} ms; ", watch.ElapsedMilliseconds));
            #endregion

            #region Canny and edge detection
            watch.Reset(); watch.Start();
            double cannyThresholdLinking = 270.0;
            UMat   cannyEdges            = new UMat();
            CvInvoke.Canny(uimage, cannyEdges, cannyThreshold, cannyThresholdLinking);

            LineSegment2D[] lines = CvInvoke.HoughLinesP(
                cannyEdges,
                1,              //Distance resolution in pixel-related units
                Math.PI / 45.0, //Angle resolution measured in radians.
                20,             //threshold
                30,             //min Line width
                10);            //gap between lines

            watch.Stop();
            outputLabel.Text += "\nL: " + lines.Length;
            msgBuilder.Append(String.Format("Canny & Hough lines - {0} ms; ", watch.ElapsedMilliseconds));
            #endregion

            #region Find triangles and rectangles
            watch.Reset(); watch.Start();
            List <Triangle2DF>   triangleList = new List <Triangle2DF>();
            List <RotatedRect>   boxList      = new List <RotatedRect>();   //a box is a rotated rectangle
            List <LineSegment2D> lineBoxes    = new List <LineSegment2D>(); //for the species that looks like a line

            using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
            {
                CvInvoke.FindContours(cannyEdges, contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple);
                int count = contours.Size;
                for (int i = 0; i < count; i++)
                {
                    using (VectorOfPoint contour = contours[i])
                        using (VectorOfPoint approxContour = new VectorOfPoint())
                        {
                            CvInvoke.ApproxPolyDP(contour, approxContour, CvInvoke.ArcLength(contour, true) * 0.05, true);
                            if (CvInvoke.ContourArea(approxContour, false) > 250) //only consider contours with area greater than 250
                            {
                                if (approxContour.Size == 3)                      //The contour has 3 vertices, it is a triangle
                                {
                                    Point[] pts = approxContour.ToArray();
                                    triangleList.Add(new Triangle2DF(
                                                         pts[0],
                                                         pts[1],
                                                         pts[2]
                                                         ));
                                }
                                else if (approxContour.Size == 4) //The contour has 4 vertices.
                                {
                                    #region determine if all the angles in the contour are within [80, 100] degree
                                    bool            isRectangle = true;
                                    Point[]         pts         = approxContour.ToArray();
                                    LineSegment2D[] edges       = PointCollection.PolyLine(pts, true);

                                    for (int j = 0; j < edges.Length; j++)
                                    {
                                        double angle = Math.Abs(
                                            edges[(j + 1) % edges.Length].GetExteriorAngleDegree(edges[j]));
                                        if (angle < 80 || angle > 100)
                                        {
                                            isRectangle = false;
                                            break;
                                        }
                                    }
                                    #endregion

                                    if (isRectangle)
                                    {
                                        boxList.Add(CvInvoke.MinAreaRect(approxContour));
                                    }
                                }
                            }
                        }
                }
            }

            watch.Stop();
            outputLabel.Text += "\nTriangles: " + triangleList.Count / 2;
            outputLabel.Text += "\nRectangles: " + boxList.Count / 2;
            msgBuilder.Append(String.Format("Triangles & Rectangles - {0} ms; ", watch.ElapsedMilliseconds));
            #endregion

            this.Text = msgBuilder.ToString();

            #region draw triangles and rectangles
            Image <Bgr, Byte> triangleRectangleImage = img.CopyBlank();
            foreach (Triangle2DF triangle in triangleList)
            {
                img.Draw(triangle, new Bgr(Color.DarkBlue), 2);
            }
            foreach (RotatedRect box in boxList)
            {
                img.Draw(box, new Bgr(Color.DarkOrange), 2);
            }
            #endregion

            #region draw circles
            Image <Bgr, Byte> circleImage = img.CopyBlank();
            foreach (CircleF circle in circles)
            {
                img.Draw(circle, new Bgr(Color.Brown), 2);
            }
            #endregion

            #region draw lines
            Image <Bgr, Byte> lineImage = img.CopyBlank();
            foreach (LineSegment2D line in lines)
            {
                img.Draw(line, new Bgr(Color.Green), 2);
            }
            #endregion

            originalImageBox.Image = img.ToBitmap();
        }
Beispiel #29
0
        public void PerformShapeDetection()
        {
            if (fileNameTextBox.Text != String.Empty)
            {
                StringBuilder msgBuilder = new StringBuilder("Performance: ");

                //Load the image from file and resize it for display
                Image <Bgr, Byte> img =
                    new Image <Bgr, byte>(fileNameTextBox.Text)
                    .Resize(400, 400, Emgu.CV.CvEnum.Inter.Linear, true);

                //Convert the image to grayscale and filter out the noise
                UMat uimage = new UMat();
                CvInvoke.CvtColor(img, uimage, ColorConversion.Bgr2Gray);

                //use image pyr to remove noise
                UMat pyrDown = new UMat();
                CvInvoke.PyrDown(uimage, pyrDown);
                CvInvoke.PyrUp(pyrDown, uimage);

                //Image<Gray, Byte> gray = img.Convert<Gray, Byte>().PyrDown().PyrUp();

                #region circle detection
                Stopwatch watch                      = Stopwatch.StartNew();
                double    cannyThreshold             = 180.0;
                double    circleAccumulatorThreshold = 120;
                CircleF[] circles                    = CvInvoke.HoughCircles(uimage, HoughType.Gradient, 2.0, 20.0, cannyThreshold, circleAccumulatorThreshold, 5);

                watch.Stop();
                msgBuilder.Append(String.Format("Hough circles - {0} ms; ", watch.ElapsedMilliseconds));
                #endregion

                #region Canny and edge detection
                watch.Reset(); watch.Start();
                double cannyThresholdLinking = 120.0;
                UMat   cannyEdges            = new UMat();
                CvInvoke.Canny(uimage, cannyEdges, cannyThreshold, cannyThresholdLinking);

                LineSegment2D[] lines = CvInvoke.HoughLinesP(
                    cannyEdges,
                    1,              //Distance resolution in pixel-related units
                    Math.PI / 45.0, //Angle resolution measured in radians.
                    20,             //threshold
                    30,             //min Line width
                    10);            //gap between lines

                watch.Stop();
                msgBuilder.Append(String.Format("Canny & Hough lines - {0} ms; ", watch.ElapsedMilliseconds));
                #endregion

                #region Find triangles and rectangles
                watch.Reset(); watch.Start();
                List <Triangle2DF> triangleList = new List <Triangle2DF>();
                List <RotatedRect> boxList      = new List <RotatedRect>(); //a box is a rotated rectangle

                using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
                {
                    CvInvoke.FindContours(cannyEdges, contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple);
                    int count = contours.Size;
                    for (int i = 0; i < count; i++)
                    {
                        using (VectorOfPoint contour = contours[i])
                            using (VectorOfPoint approxContour = new VectorOfPoint())
                            {
                                CvInvoke.ApproxPolyDP(contour, approxContour, CvInvoke.ArcLength(contour, true) * 0.05, true);
                                if (CvInvoke.ContourArea(approxContour, false) > 250) //only consider contours with area greater than 250
                                {
                                    if (approxContour.Size == 3)                      //The contour has 3 vertices, it is a triangle
                                    {
                                        Point[] pts = approxContour.ToArray();
                                        triangleList.Add(new Triangle2DF(
                                                             pts[0],
                                                             pts[1],
                                                             pts[2]
                                                             ));
                                    }
                                    else if (approxContour.Size == 4) //The contour has 4 vertices.
                                    {
                                        #region determine if all the angles in the contour are within [80, 100] degree
                                        bool            isRectangle = true;
                                        Point[]         pts         = approxContour.ToArray();
                                        LineSegment2D[] edges       = PointCollection.PolyLine(pts, true);

                                        for (int j = 0; j < edges.Length; j++)
                                        {
                                            double angle = Math.Abs(
                                                edges[(j + 1) % edges.Length].GetExteriorAngleDegree(edges[j]));
                                            if (angle < 80 || angle > 100)
                                            {
                                                isRectangle = false;
                                                break;
                                            }
                                        }
                                        #endregion

                                        if (isRectangle)
                                        {
                                            boxList.Add(CvInvoke.MinAreaRect(approxContour));
                                        }
                                    }
                                }
                            }
                    }
                }

                watch.Stop();
                msgBuilder.Append(String.Format("Triangles & Rectangles - {0} ms; ", watch.ElapsedMilliseconds));
                #endregion

                originalImageBox.Image = img;
                this.Text = msgBuilder.ToString();

                #region draw triangles and rectangles
                Mat triangleRectangleImage = new Mat(img.Size, DepthType.Cv8U, 3);
                triangleRectangleImage.SetTo(new MCvScalar(0));
                foreach (Triangle2DF triangle in triangleList)
                {
                    CvInvoke.Polylines(triangleRectangleImage, Array.ConvertAll(triangle.GetVertices(), Point.Round), true, new Bgr(Color.DarkBlue).MCvScalar, 2);
                }
                foreach (RotatedRect box in boxList)
                {
                    CvInvoke.Polylines(triangleRectangleImage, Array.ConvertAll(box.GetVertices(), Point.Round), true, new Bgr(Color.DarkOrange).MCvScalar, 2);
                }

                triangleRectangleImageBox.Image = triangleRectangleImage;
                #endregion

                #region draw circles
                Mat circleImage = new Mat(img.Size, DepthType.Cv8U, 3);
                circleImage.SetTo(new MCvScalar(0));
                foreach (CircleF circle in circles)
                {
                    CvInvoke.Circle(circleImage, Point.Round(circle.Center), (int)circle.Radius, new Bgr(Color.Brown).MCvScalar, 2);
                }

                circleImageBox.Image = circleImage;
                #endregion

                #region draw lines
                Mat lineImage = new Mat(img.Size, DepthType.Cv8U, 3);
                lineImage.SetTo(new MCvScalar(0));
                foreach (LineSegment2D line in lines)
                {
                    CvInvoke.Line(lineImage, line.P1, line.P2, new Bgr(Color.Green).MCvScalar, 2);
                }

                lineImageBox.Image = lineImage;
                #endregion
            }
        }
Beispiel #30
0
        public void GetBoundries(Image <Gray, Byte> binaryBackground, out List <Point[]> boundries, out List <Point[]> artefacts, out List <RotatedRect> boxes)
        {
            //Find outer boundries
            double minimumContourArea = 250;
            double minimumBoundryArea = 1000;
            //double approximationFactor = 0.001;
            List <Point[]>     allBoundries = new List <Point[]>();
            List <Point[]>     allObjects   = new List <Point[]>();
            List <RotatedRect> boxList      = new List <RotatedRect>();

            using (Image <Gray, Byte> filteredBinary = binaryBackground.SmoothMedian(7))
                using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
                    using (Mat hierarchy = new Mat())
                    {
                        CvInvoke.FindContours(filteredBinary, contours, hierarchy, RetrType.Tree, ChainApproxMethod.ChainApproxNone);
                        var temp = hierarchy.ToImage <Bgra, Byte>();

                        int        count      = contours.Size;
                        List <int> boundryIds = new List <int>();
                        for (int i = 0; i < count; i++)
                        {
                            using (VectorOfPoint contour = contours[i])
                            {
                                double contourArea = CvInvoke.ContourArea(contour);

                                if (contourArea >= minimumBoundryArea)
                                {
                                    Bgra currentContour = temp[0, i];
                                    if (currentContour.Alpha == 0)
                                    {
                                        allBoundries.Add(contour.ToArray());
                                        boundryIds.Add(i);
                                    }
                                }
                            }
                        }

                        for (int i = 0; i < count; i++)
                        {
                            using (VectorOfPoint contour = contours[i])
                            {
                                double contourArea = CvInvoke.ContourArea(contour);

                                if (contourArea >= minimumContourArea)
                                {
                                    Bgra currentContour = temp[0, i];

                                    if (!boundryIds.Contains(i) && boundryIds.Contains((int)currentContour.Alpha))
                                    {
                                        bool isRectangle = true;
                                        bool isCircle    = false;
                                        //Can the object be approximated as a circle or rectangle?
                                        using (VectorOfPoint apxContour = new VectorOfPoint())
                                        {
                                            double epsilon = CvInvoke.ArcLength(contour, true) * 0.05;
                                            CvInvoke.ApproxPolyDP(contour, apxContour, epsilon, true);

                                            if (apxContour.Size == 4) //The contour has 4 vertices.
                                            {
                                                Point[]         pts   = apxContour.ToArray();
                                                LineSegment2D[] edges = PointCollection.PolyLine(pts, true);

                                                for (int j = 0; j < edges.Length; j++)
                                                {
                                                    double angle = Math.Abs(edges[(j + 1) % edges.Length].GetExteriorAngleDegree(edges[j]));
                                                    if (angle < 70 || angle > 110)
                                                    {
                                                        isRectangle = false;
                                                        break;
                                                    }
                                                }

                                                if (isRectangle)
                                                {
                                                    boxList.Add(CvInvoke.MinAreaRect(apxContour));
                                                }
                                            }
                                            else
                                            {
                                                isRectangle = false;
                                            }
                                        }

                                        if (!isRectangle && !isCircle)
                                        {
                                            allObjects.Add(contour.ToArray());
                                        }
                                    }
                                }
                            }
                        }
                    }

            //Find mouse
            //mousePoints = null;
            //using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
            //{
            //    CvInvoke.FindContours(binaryMouse, contours, null, RetrType.External, ChainApproxMethod.ChainApproxNone);

            //    int count = contours.Size;
            //    double maxArea = 0;
            //    for (int j = 0; j < count; j++)
            //    {
            //        using (VectorOfPoint contour = contours[j])
            //        {
            //            double contourArea = CvInvoke.ContourArea(contour);
            //            if (contourArea >= maxArea)
            //            {
            //                maxArea = contourArea;
            //                mousePoints = contour.ToArray();
            //            }
            //        }
            //    }
            //}

            boundries = allBoundries;
            artefacts = allObjects;
            boxes     = boxList;
            //Check if any contours can be approximated as shapes


            //We now have a list of boundries, if there's more than one it means something is sticking across the screen
            if (allBoundries.Count > 1)
            {
                //Need to find points from all boundries that are effectively parallel
            }

            //Image<Bgr, Byte> allContourImage = FirstFrame.Clone();

            //allContourImage.DrawPolyline(mousePoints, true, new Bgr(Color.Yellow), 2);
            //allContourImage.DrawPolyline(allBoundries.ToArray(), true, new Bgr(Color.Red), 2);
            //allContourImage.DrawPolyline(allObjects.ToArray(), true, new Bgr(Color.LightGreen), 2);
            //foreach (var box in boxList)
            //{
            //    allContourImage.Draw(box.GetVertices().Select(x => new Point((int)x.X, (int)x.Y)).ToArray(), new Bgr(Color.Aqua), 2);
            //}
        }