public AlgorithmResult DetectContours(
            string filename,
            ContourRetrType rtype,
            ContourMethodType mtype,
            double threshold1,
            double threshold2,
            int apertureSize)
        {
            AlgorithmResult   result = new AlgorithmResult();
            Image <Bgr, byte> image  = ImageHelper.GetImage(filename);
            var cannyImage           = new Image <Gray, byte>(image.Width, image.Height);
            var resultImage          = new Image <Bgr, byte>(filename);
            var contours             = new VectorOfVectorOfPoint();

            // Apply canny algorithm
            CvInvoke.Canny(
                image.Convert <Gray, byte>(),
                cannyImage,
                threshold1,
                threshold2,
                apertureSize);

            // Find the contours
            CvInvoke.FindContours(
                cannyImage,
                contours,
                null,
                GetRetrType(rtype),
                GetMethodType(mtype));

            resultImage = cannyImage.Convert <Bgr, byte>();

            // Draw the contours
            resultImage.DrawPolyline(
                contours.ToArrayOfArray(),
                false,
                new Bgr(Color.FromArgb(255, 77, 77)),
                3);

            // Return collection of contours
            result.ImageArray   = ImageHelper.SetImage(resultImage);
            result.ContourDatas = new List <ContourPointModel>();
            result.ContourDatas = contours.ToArrayOfArray().Select(c => new ContourPointModel()
            {
                Count  = c.Select(p => new PointF(p.X, p.Y)).ToArray().Length,
                StartX = c.Length > 0 ? c[0].X : float.NaN,
                StartY = c.Length > 0 ? c[0].Y : float.NaN,
                EndX   = c.Length > 0 ? c[c.Length - 1].X : float.NaN,
                EndY   = c.Length > 0 ? c[c.Length - 1].Y : float.NaN,
                Length = GetLength(c.Select(p => new PointF(p.X, p.Y)).ToArray())
            }).ToList();

            return(result);
        }
示例#2
0
        /// <summary>
        /// Detect scene text from the given image
        /// </summary>
        /// <param name="image">The image</param>
        /// <returns>The detected scene text.</returns>
        public DetectedObject[] Detect(IInputArray image)
        {
            using (VectorOfVectorOfPoint vvp = new VectorOfVectorOfPoint())
                using (VectorOfFloat confidents = new VectorOfFloat())
                {
                    _textDetector.Detect(image, vvp, confidents);

                    Point[][]             detectionResults = vvp.ToArrayOfArray();
                    float[]               confidentResult  = confidents.ToArray();
                    List <DetectedObject> results          = new List <DetectedObject>();
                    for (int i = 0; i < detectionResults.Length; i++)
                    {
                        DetectedObject st             = new DetectedObject();
                        PointF[]       detectedPointF =
                            Array.ConvertAll(detectionResults[i], p => new PointF((float)p.X, (float)p.Y));
                        st.Region    = CvInvoke.BoundingRectangle(detectionResults[i]);
                        st.Confident = confidentResult[i];

                        using (Mat textSubMat = new Mat())
                        {
                            FourPointsTransform(image, detectedPointF, new Size(100, 32), textSubMat);
                            String text = _ocr.Recognize(textSubMat);
                            st.Label = text;
                        }

                        results.Add(st);
                    }

                    return(results.ToArray());
                }
        }
示例#3
0
        public List <Contour> Contours(RetrType retrievalMode = RetrType.Tree, ChainApproxMethod approximationMethod = ChainApproxMethod.ChainApproxSimple)
        {
            VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
            Mat hierarchy = new Mat();

            CvInvoke.FindContours(this.Data, contours, hierarchy, retrievalMode, approximationMethod);

            Point[][] contourArray = contours.ToArrayOfArray();
            int[,,] hierarchyArray = (int[, , ])hierarchy.GetData();

            List <Contour> output = new List <Contour>();

            for (int i = 0; i < contourArray.Length; i++)
            {
                Contour c = new Contour(contourArray[i])
                {
                    Hierarchy = new int[] {
                        hierarchyArray[0, i, 0],
                        hierarchyArray[0, i, 1],
                        hierarchyArray[0, i, 2],
                        hierarchyArray[0, i, 3],
                    }
                };

                output.Add(c);
            }

            return(output);
        }
示例#4
0
        private void Draw(Mat image, int x, int y)
        {
            VectorOfVectorOfPoint cnt = new VectorOfVectorOfPoint();

            CvInvoke.FindContours(image, cnt, null, RetrType.List, ChainApproxMethod.ChainApproxNone);

            Point[][] pts = cnt.ToArrayOfArray();

            for (int i = 0; i < pts.Length; i++)
            {
                for (int j = 0; j < pts[i].Length; j++)
                {
                    Point pt = pts[i][j];
                    if ((_lastPoint.X != -1 && !_lastPoint.Equals(MousePosition)) || _pid != GetActiveProcess())
                    {
                        return;
                    }

                    pt.X += x;
                    pt.Y += y;

                    LeftMouseClick(pt.X, pt.Y, pt.X, pt.Y);
                    Thread.Sleep(10);
                }
            }
            Fill(image, x, y);
        }
示例#5
0
 public static List <RawDefectInfo> FindDefectInfo(
     this VectorOfVectorOfPoint src)
 {
     return(src?.ToArrayOfArray()
            .Select(ptarr => ptarr.PointArr2DefectInfo())
            .ToList());
 }
示例#6
0
        public void _findOutline()
        {
            using (var im = _mat.Clone())
            {
                VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
                CvInvoke.FindContours(im, contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple);

                var cts = contours.ToArrayOfArray()
                          .Select(x => CvInvoke.ConvexHull(x.Select(y => new PointF(y.X, y.Y)).ToArray())).ToArray();

                var cnt = cts.OrderByDescending(z => CvInvoke.ContourArea(new VectorOfPointF(z))).ToList();

                var result = new VectorOfPointF();

                foreach (var c in cnt)
                {
                    var vop  = new VectorOfPointF(c);
                    var peri = CvInvoke.ArcLength(vop, true);

                    var approx = new VectorOfPointF();
                    CvInvoke.ApproxPolyDP(vop, approx, _approxE * peri, true);

                    if (approx.Size == 4)
                    {
                        result = approx;
                        break;
                    }
                }

                _outline = result;
            }
        }
示例#7
0
        public override void Process(Image <Bgr, byte> image, out Image <Bgr, byte> annotatedImage, out List <object> data)
        {
            base.Process(image, out annotatedImage, out data);

            using (var contours = new VectorOfVectorOfPoint())
            {
                // find the contours for an image
                CvInvoke.FindContours(image.Convert <Gray, byte>(), contours, null, _mode, _method);

                // draw the contours
                annotatedImage.DrawPolyline(contours.ToArrayOfArray(), false, new Bgr(_annoColor.Color()), _lineThick);

                // return collection of contours
                data = contours.ToArrayOfArray().Select(c => new Contour(c)).Cast <object>().ToList();
            }
        }
示例#8
0
        public override void Process(Image <Bgr, byte> image, out Image <Bgr, byte> annotatedImage, out List <object> data)
        {
            base.Process(image, out annotatedImage, out data);

            using (var contours = new VectorOfVectorOfPoint())
            {
                // find the contours
                CvInvoke.FindContours(
                    image.Convert <Gray, byte>(),
                    contours,
                    null,
                    RetrType.List,
                    ChainApproxMethod.ChainApproxSimple);

                // optionally show the contours
                if (_showContours)
                {
                    annotatedImage.DrawPolyline(contours.ToArrayOfArray(), false, new Bgr(_contourColor.Color()), _lineThick);
                }

                // flatten the points of the contours into a single array
                var points = contours
                             .ToArrayOfArray()
                             .SelectMany(c => c)
                             .Select(p => new PointF(p.X, p.Y))
                             .ToArray();

                // get the convex hull
                var convexHull = CvInvoke.ConvexHull(points);

                // draw the convex hull
                annotatedImage.DrawPolyline(
                    convexHull.Select(Point.Round).ToArray(),
                    true,
                    new Bgr(_annoColor.Color()),
                    _lineThick);

                // set the data as a single contour for the convex hull
                data = new List <object> {
                    new Contour(convexHull)
                };
            }
        }
        public void MSER()
        {
            var sourceBitmap = Samples.sample13;

            var w = sourceBitmap.Width;
            var h = sourceBitmap.Height;

            using var src = new UMat();

            using var srcMat = sourceBitmap.ToMat();
            srcMat.CopyTo(src);

            using var gray = new UMat();

            CvInvoke.CvtColor(src, gray, ColorConversion.Bgra2Gray);

            using var detector = new MSERDetector(
                      minArea: 5, maxArea: 80, edgeBlurSize: 5);
            using var msers  = new VectorOfVectorOfPoint();
            using var bboxes = new VectorOfRect();

            detector.DetectRegions(gray, msers, bboxes);

            var sw = new Stopwatch();

            sw.Start();

            var n = 100;

            for (var i = 0; i < n; i++)
            {
                detector.DetectRegions(gray, msers, bboxes);
            }

            sw.Stop();

            Console.WriteLine($"{(int)(sw.Elapsed.TotalMicroseconds() / n)} us");

            var result = new byte[w * h];

            foreach (var mser in msers.ToArrayOfArray())
            {
                foreach (var point in mser)
                {
                    result[point.Y * w + point.X] = 255;
                }
            }
            foreach (var bbox in bboxes.ToArray())
            {
            }


            Run("samples/sample13.png");
            //result.RunAs(w, h, 1, "mser.png");
        }
示例#10
0
        public static Func <VectorOfVectorOfPoint> FnSortcontours(VectorOfVectorOfPoint inputContours)
        {
            var sort = new Func <VectorOfVectorOfPoint>(() =>
            {
                var temp   = inputContours.ToArrayOfArray();
                var sorted = temp.OrderBy(p => p[0].Y).ThenBy(p => p[0].X).ToArray();
                return(new VectorOfVectorOfPoint(sorted));
            });

            return(sort);
        }
示例#11
0
        private static IEnumerable <Point[]> FindContours(Bitmap image)
        {
            using (var cvImage = image.ToCvImage())
            {
                var contour = new VectorOfVectorOfPoint();

                CvInvoke.CvtColor(cvImage, cvImage, ColorConversion.Rgb2Gray);
                CvInvoke.FindContours(cvImage, contour, new Mat(), RetrType.External, ChainApproxMethod.ChainApproxTc89Kcos);

                return(contour.ToArrayOfArray());
            }
        }
示例#12
0
 public static List <RotatedRect> FindMinimalBox(
     this VectorOfVectorOfPoint src)
 {
     return(src?.ToArrayOfArray()
            .Select(ptarr =>
                    ptarr.Select(pt =>
                                 new System.Drawing.PointF(pt.X, pt.Y))
                    .ToArray())
            .ToArray()
            .Select(ptfArr => CvInvoke.MinAreaRect(ptfArr))
            .ToList());
 }
示例#13
0
        /// <summary>
        /// Bound the contours.
        /// </summary>
        /// <param name="contours">The contours.</param>
        /// <param name="annotatedImage">The image with bound rectangles.</param>
        /// <param name="data">The raw data for rectangles.</param>
        private void BoundContours(VectorOfVectorOfPoint contours, ref Image <Bgr, byte> annotatedImage, ref List <object> data)
        {
            // optionally show the contours
            if (_showContours)
            {
                annotatedImage.DrawPolyline(contours.ToArrayOfArray(), false, new Bgr(_contourColor.Color()), _lineThick);
            }

            // bound object for each contour or all contours
            if (!_foreachContour)
            {
                var points = contours.ToArrayOfArray().SelectMany(p => p).ToArray();
                FindRect(new VectorOfPoint(points), ref annotatedImage, ref data);
            }
            else
            {
                foreach (var contour in contours.ToArrayOfArray())
                {
                    FindRect(new VectorOfPoint(contour), ref annotatedImage, ref data);
                }
            }
        }
示例#14
0
        private void ProcessImage()
        {
            while (true)
            {
                // Read from webcam
                Mat m = new Mat();
                capture.Read(m);
                img = m.Clone().ToImage <Bgr, byte>();
                Image <Bgr, byte> tempImage = img.Clone();

                // Blur image to remove noise
                tempImage = tempImage.SmoothGaussian(5);

                // Threshold image to find regions
                var greyImage = tempImage.Convert <Gray, byte>().ThresholdBinary(new Gray(100), new Gray(255));
                VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();

                // Get points along edges
                CvInvoke.FindContours(greyImage, contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple);

                // For debugging output
                CvInvoke.DrawContours(tempImage, contours, -1, new MCvScalar(1, 1, 0), -1);


                foreach (var contour in contours.ToArrayOfArray())
                {
                    VectorOfPoint poly = new VectorOfPoint();

                    // Finds polygon of contour
                    CvInvoke.ApproxPolyDP(new VectorOfPoint(contour), poly, CvInvoke.ArcLength(new VectorOfPoint(contour), true) * 0.05, true);

                    // Draw corners
                    foreach (var point in poly.ToArray())
                    {
                        tempImage.Draw(new CircleF(point, 2), new Bgr(255, 255, 0), -1);
                    }

                    // Triangle
                    if (poly.Size == 3)
                    {
                        // Paint it blue
                        tempImage.FillConvexPoly(poly.ToArray(), new Bgr(255, 0, 0));
                    }
                }

                // Update display
                pictureBoxFilter.Image   = tempImage.ToBitmap();
                pictureBoxOriginal.Image = img.ToBitmap();
                Thread.Sleep(1);
            }
        }
示例#15
0
        // 补全轮廓并填充
        private Image <Bgr, byte> ContourFilling(Image <Gray, byte> pic)
        {
            Image <Bgr, byte> outpic = new Image <Bgr, byte>(pic.Size);

            pic = pic.Canny(100, 255);
            Image <Gray, byte>    outcon = new Image <Gray, byte>(pic.Size);
            VectorOfVectorOfPoint con    = new VectorOfVectorOfPoint();

            CvInvoke.FindContours(pic, con, outcon, RetrType.External, ChainApproxMethod.ChainApproxNone);
            Point[][]  con1 = con.ToArrayOfArray();
            PointF[][] con2 = Array.ConvertAll(con1, new Converter <Point[], PointF[]>(PointToPointF));
            PointF[]   hull = new PointF[con[0].Size];
            for (int i = 0; i < con.Size; i++)
            {
                hull = CvInvoke.ConvexHull(con2[i], true);
                for (int j = 0; j < hull.Length; j++)
                {
                    Point p1 = new Point((int)(hull[j].X + 0.5), (int)(hull[j].Y + 0.5));
                    Point p2;
                    if (j == hull.Length - 1)
                    {
                        p2 = new Point((int)(hull[0].X + 0.5), (int)(hull[0].Y + 0.5));
                    }
                    else
                    {
                        p2 = new Point((int)(hull[j + 1].X + 0.5), (int)(hull[j + 1].Y + 0.5));
                    }
                    CvInvoke.Line(outpic, p1, p2, new MCvScalar(255, 0, 255, 255), 2, 0, 0);
                }
            }

            Image <Gray, byte> gray = new Image <Gray, byte>(pic.Size);

            gray = outpic.Convert <Gray, byte>();
            gray = gray.ThresholdBinary(new Gray(100), new Gray(255));
            gray = gray.Canny(100, 255);
            VectorOfVectorOfPoint con3 = new VectorOfVectorOfPoint();

            CvInvoke.FindContours(gray, con3, outcon, RetrType.External, ChainApproxMethod.ChainApproxNone);
            for (int i = 0; i < con3.Size; i++)
            {
                CvInvoke.DrawContours(outpic, con3, i, new MCvScalar(255, 0, 0), -1);
            }

            return(outpic);
        }
示例#16
0
    public void ApplyFilter(Mat src)
    {
        CvInvoke.CvtColor(src, src, ColorConversion.Bgr2Hsv);

        Mat       threshold = new Mat(src.Height, src.Width, src.Depth, src.NumberOfChannels);
        MCvScalar min       = new MCvScalar(m_hmin, m_smin, m_vmin);
        MCvScalar max       = new MCvScalar(m_hmax, m_smax, m_vmax);

        CvInvoke.InRange(src, new ScalarArray(min), new ScalarArray(max), threshold);

        Mat element = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(3, 3), Point.Empty);

        CvInvoke.Erode(threshold, threshold, element, Point.Empty, 1, BorderType.Constant, new MCvScalar(1.0f));
        CvInvoke.Canny(threshold, threshold, 100, 255);

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

        CvInvoke.FindContours(threshold, contours, hierarchy, RetrType.Tree, ChainApproxMethod.ChainApproxSimple, Point.Empty);

        Mat draw = new Mat(src.Height, src.Width, src.Depth, 1);

        draw.SetTo(new MCvScalar(0.0));
        int i = 0;

        //Debug.Log("CONTOURS");

        var contoursArray = contours.ToArrayOfArray();

        foreach (Point[] contour in contoursArray)
        {
            CvInvoke.DrawContours(draw, contours, i, new MCvScalar(255.0), 1, LineType.EightConnected, null, int.MaxValue, Point.Empty);

            double a = CvInvoke.ContourArea(new VectorOfPoint(contour));
            //Debug.Log("Contour: " + a);
            i++;
        }

        //Emgu.CV.UI.ImageViewer.Show(draw, "test");

        if (m_onFrame != null)
        {
            m_onFrame.Invoke(draw);
        }
    }
示例#17
0
        //OnClick of Capture Button
        private void Button1_Click(object sender, EventArgs e)
        {
            try
            {
                if (worker != null)
                {
                    worker.Abort();
                }

                using (var img = new Image <Bgr, byte>(CaptureScreen(Helper.ScreenBounds())))
                {
                    var filtrdimg = img.InRange(new Bgr(189, 189, 189), new Bgr(205, 205, 205)); //Threshold the image, the window we need is usually within these colors

                    VectorOfVectorOfPoint cnts = new VectorOfVectorOfPoint();
                    CvInvoke.FindContours(filtrdimg, cnts, null, Emgu.CV.CvEnum.RetrType.External, Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple); //Get contours in the thresholded image
                    var biggstcontour = (from u in cnts.ToArrayOfArray()
                                         orderby CvInvoke.ContourArea(new VectorOfPoint(u)) descending
                                         select u).FirstOrDefault(); //Get the contour with the biggest area

                    /* Store the location of the biggest contour */
                    regionRectangle = CvInvoke.BoundingRectangle(new VectorOfPoint(biggstcontour));
                    selectX         = regionRectangle.X;
                    selectY         = regionRectangle.Y;

                    using (var imgcrpd = new Image <Bgr, byte>(CaptureScreen(regionRectangle)))
                    {
                        using (var template = new Image <Bgr, Byte>("startsmile.png"))                            //startmsile.png is the smiley that appears on game start
                        {
                            var res = imgcrpd.MatchTemplate(template, Emgu.CV.CvEnum.TemplateMatchingType.Ccorr); //Match the smiley to find the contour of the game window
                            res.MinMax(out double[] min_val, out double[] max_val, out Point[] min_loc, out Point[] max_loc);

                            startcords = new Point(selectX + max_loc[0].X + 7, selectY + max_loc[0].Y + 7); //Get the coordinates of the smiley button, with 7px extra to account for middle of the button

                            DoLogic(regionRectangle);
                        }
                    }
                }
            }
            catch
            {
                MessageBox.Show("The game window was not found. This programs only supports the Windows XP Minesweeper application or http://minesweeperonline.com/");
            }
        }
        //sort contours
        public void contourSort()
        {
            sortedContours.Clear();
            List <List <Point> > list = arrToList(contours.ToArrayOfArray());

            sortedContours.Add(extractVector(list, 0));      // extract the first vector
            while (list.Count != 0)
            {
                int save = 0;
                //find the closest vector
                for (int i = 1; i < list.Count; i++)
                {
                    if (isVectorCloser(sortedContours.Last(), list[i], list[save]))
                    {
                        save = i;
                    }
                }
                //sort and insert vector into contours object
                contourSortInsert(ref sortedContours, extractVector(list, save));
            }
        }
示例#19
0
        private void button2_Click(object sender, EventArgs e)
        {
            Image <Gray, byte> image2 = new Image <Gray, byte>(image1.Width, image1.Height);
            Image <Gray, byte> image3 = new Image <Gray, byte>(image1.Width, image1.Height);
            Image <Bgr, byte>  image4 = new Image <Bgr, byte>(image1.Width, image1.Height);

            CvInvoke.Canny(image1, image2, 100, 60);
            VectorOfVectorOfPoint con = new VectorOfVectorOfPoint();

            CvInvoke.FindContours(image2, con, image3, RetrType.Ccomp, ChainApproxMethod.ChainApproxSimple);

            Point[][]  con1 = con.ToArrayOfArray();
            PointF[][] con2 = Array.ConvertAll <Point[], PointF[]>(con1, new Converter <Point[], PointF[]>(PointToPointF));
            for (int i = 0; i < con.Size; i++)
            {
                PointF[] hull = CvInvoke.ConvexHull(con2[i], true);
                for (int j = 0; j < hull.Length; j++)
                {
                    Point p1 = new Point((int)(hull[j].X + 0.5), (int)(hull[j].Y + 0.5));
                    Point p2;
                    if (j == hull.Length - 1)
                    {
                        p2 = new Point((int)(hull[0].X + 0.5), (int)(hull[0].Y + 0.5));
                    }
                    else
                    {
                        p2 = new Point((int)(hull[j + 1].X + 0.5), (int)(hull[j + 1].Y + 0.5));
                    }
                    CvInvoke.Circle(image4, p1, 3, new MCvScalar(0, 255, 255, 255), 6);
                    CvInvoke.Line(image4, p1, p2, new MCvScalar(255, 255, 0, 255), 3);
                }
            }
            for (int i = 0; i < con.Size; i++)
            {
                CvInvoke.DrawContours(image4, con, i, new MCvScalar(255, 0, 255, 255), 2);
            }

            imageBox2.Image = image1.ConcateVertical(image4);
        }
        public void UpdateInfo(VectorOfVectorOfPoint VVP)
        {
            Contours = VVP;
            rect     = new System.Drawing.Rectangle[Contours.Size];
            if (Contours.Size <= threshold)
            {
                masterHeights = new List <double>();
                masterWidths  = new List <double>();
                masterArea    = new List <double>();
                masterCenterX = new List <double>();
                masterCenterY = new List <double>();

                Points = VVP.ToArrayOfArray();
                getRectangles();
                publish();
            }
            else
            {
                Console.WriteLine("Threshold of {0} contours has been met. \nStopping processing of contours.", threshold);
            }
            //iterate();
        }
        public Result <Point[][]> Process(Mat input)
        {
            var contoursDetected = new VectorOfVectorOfPoint();

            CvInvoke.FindContours(input, contoursDetected, null, RetrType.List, ChainApproxMethod.ChainApproxSimple);
            var contours = contoursDetected.ToArrayOfArray();
            Result <Point[][]> result;

            if (contours.Length > 0)
            {
                result = Result.Ok(contours);
            }
            else
            {
                result = Result.Fail <Point[][]>("Contours hasn't been found");
            }

            _debugLogger.Log(logBuilder =>
            {
                if (result.Success)
                {
                    var imageToDrawContours = new Mat(input.Size, DepthType.Cv8U, 3);
                    imageToDrawContours.SetTo(new MCvScalar(0, 0, 0));
                    var random = new Random();
                    for (int i = 0; i < contours.Length; i++)
                    {
                        CvInvoke.DrawContours(imageToDrawContours, contoursDetected, i, new MCvScalar(random.Next(255), random.Next(255), random.Next(255)));
                    }
                    logBuilder.AddMessage($"Found {contours.Length} contours").AddImage(imageToDrawContours);
                }
                else
                {
                    logBuilder.AddMessage(result.Error);
                }
            });

            return(result);
        }
示例#22
0
        /// <summary>Поиск контура объекта</summary><returns>Изображение с выделенным контуром объекта</returns>
        /// реализовать проверку на наличие изображения в pictureBox
        /// Реализовать нахождения максимального по площади контура

        private Image <Bgr, byte> searchСounters()
        {
            try
            {
                Image <Gray, byte>    outputImage = image.Convert <Gray, byte>().ThresholdBinary(new Gray(150), new Gray(255));
                VectorOfVectorOfPoint countors    = new VectorOfVectorOfPoint();
                Mat hierarchy = new Mat();
                CvInvoke.FindContours(inversion(outputImage), countors, hierarchy, Emgu.CV.CvEnum.RetrType.Tree, Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxNone);
                Image <Bgr, byte> save = new Image <Bgr, byte>(image.Width, image.Height, new Bgr(255, 255, 255));
                CvInvoke.DrawContours(save, countors, 0, new MCvScalar(0, 0, 255), 1);
                CvInvoke.DrawContours(image, countors, 0, new MCvScalar(0, 0, 255), 1);
                save.Save("C:\\Users\\PC\\Desktop\\Тестовые изображения\\test2.png");
                Point[][] list;
                list = countors.ToArrayOfArray();
                Point[] test;
                test = list[0];
                int[] point = CharacteristicObject.Curvature_calculation_points_counter(test);
                listBox1.Items.Add("Выпуклые 90: " + point[0]);
                listBox1.Items.Add("Вогнутые 90: " + point[1]);
                listBox1.Items.Add("Выпуклые 135: " + point[2]);
                listBox1.Items.Add("Вогнутые 135: " + point[3]);
                listBox1.Items.Add("Нулевая кривизна: " + point[4]);
                int[] pointN = CharacteristicObject.SearchForConnectedPoints(test);
                listBox1.Items.Add("N1: " + pointN[0]);
                listBox1.Items.Add("N2: " + pointN[1]);
                listBox1.Items.Add("N3: " + pointN[2]);
                listBox1.Items.Add("N4: " + pointN[3]);
                listBox1.Items.Add("N5: " + pointN[4]);
                listBox1.Items.Add("N6: " + pointN[5]);
                listBox1.Items.Add("N7: " + pointN[6]);
                listBox1.Items.Add("N8: " + pointN[7]);
                return(save);
            }
            catch (ExeptionSearchСounters ex)
            {
                throw new ExeptionSearchСounters(ex);
            }
        }
示例#23
0
        private void test(Image <Gray, byte> img)
        {
            int n = Convert.ToInt32(comboBox1.SelectedIndex);

            isCouterFind = false;
            //Image<Gray, byte> Dyncontour = new Image<Gray, byte>(src.Size);
            //VectorOfVectorOfPoint use_Dyncontour = new VectorOfVectorOfPoint();
            //VectorOfVectorOfPoint Dynstorage = new VectorOfVectorOfPoint();

            Mat dst1 = new Mat();

            CvInvoke.Threshold(img, dst1, threshold_value, 255, threshs[n]);
            // imageBox2.Image = dst1.Bitmap;
            VectorOfVectorOfPoint vvp     = new VectorOfVectorOfPoint();
            VectorOfVectorOfPoint use_vvp = new VectorOfVectorOfPoint();

            CvInvoke.FindContours(dst1, vvp, null, Emgu.CV.CvEnum.RetrType.List, Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple);
            int number = vvp.ToArrayOfArray().Length;//取得轮廓的数量.

            for (int i = 0; i < number; i++)
            {
                VectorOfPoint vp   = vvp[i];
                double        area = CvInvoke.ContourArea(vp);
                if (area > minArea && area < maxArea) //可按实际图片修改
                {
                    use_vvp.Push(vp);
                }
            }
            if (use_vvp.Size > 0)
            {
                Mat result = new Mat(img.Size, Emgu.CV.CvEnum.DepthType.Cv8U, 3);
                result.SetTo(new MCvScalar(0, 0, 0));
                CvInvoke.DrawContours(result, use_vvp, -1, new MCvScalar(0, 255, 0));

                imageBox2.Image = result;
            }
        }
示例#24
0
        /// <summary>
        /// 身份证号区域
        /// </summary>
        /// <param name="img"></param>
        /// <returns></returns>
        public static RotatedRect IdRotatedRect(Image <Bgr, byte> img)
        {
            Image <Bgr, byte>     a   = new Image <Bgr, byte>(img.Size);
            VectorOfVectorOfPoint con = GetContours(BinImg(img));

            Point[][]  con1 = con.ToArrayOfArray();
            PointF[][] con2 = Array.ConvertAll <Point[], PointF[]>(con1, new Converter <Point[], PointF[]>(PointToPointF));
            for (int i = 0; i < con.Size; i++)
            {
                RotatedRect rrec = CvInvoke.MinAreaRect(con2[i]);
                float       w    = rrec.Size.Width;
                float       h    = rrec.Size.Height;
                if (w / h > 6 && w / h < 10 && h > 20)
                {
                    PointF[] pointfs = rrec.GetVertices();
                    for (int j = 0; j < pointfs.Length; j++)
                    {
                        CvInvoke.Line(a, new Point((int)pointfs[j].X, (int)pointfs[j].Y), new Point((int)pointfs[(j + 1) % 4].X, (int)pointfs[(j + 1) % 4].Y), new MCvScalar(0, 0, 255, 255), 4);
                    }
                    return(rrec);
                }
            }
            return(new RotatedRect());
        }
示例#25
0
        public static Contours GetContours(System.Drawing.Bitmap bmp)
        {
            //var newbmp = bmp.Scale(2);

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

            //var imgfile = AppDomain.CurrentDomain.BaseDirectory + imageUrl;


            //Load the image from file and resize it for display
            Image <Gray, Byte> img = new Image <Gray, byte>(bmp);

            //.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);

            //var imageGray = img.Convert<Gray, Byte>();
            //var imagethreshold = img.ThresholdBinary(new Gray(1), new Gray(255));
            CvInvoke.Threshold(img, img, 1, 255, ThresholdType.Binary);
            //imagethreshold.FillConvexPoly();
            //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 = 100;//180.0;
            //double cannyThresholdLinking = 100;//120.0;
            //UMat cannyEdges = new UMat();
            //CvInvoke.Canny(uimage, cannyEdges, cannyThreshold, cannyThresholdLinking);

            //int[,] tempStructure = { { 1, 1, 1 } };
            //Mat structuringElement = CvInvoke.GetStructuringElement(ElementShape.Ellipse, new System.Drawing.Size(2, 2), new System.Drawing.Point(-1, -1));


            //CvInvoke.Dilate(img, img, structuringElement, new System.Drawing.Point(-1, -1), 1, BorderType.Default, new MCvScalar(0, 0, 0));

            //CvInvoke.Dilate(img, img, structuringElement, new System.Drawing.Point(-1, -1), 1, BorderType.Default,
            //    new MCvScalar(0, 0, 0));
            //CvInvoke.Erode(img, img, structuringElement, new System.Drawing.Point(-1, -1), 1, BorderType.Default,
            //    new MCvScalar(0, 0, 0));


            /////////////////////////////////////
            using (Mat hierachy = new Mat())
                using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
                {
                    CvInvoke.FindContours(img, contours, hierachy, RetrType.Tree, ChainApproxMethod.ChainApproxSimple);
                    //CvInvoke.DrawContours();

                    //////////////////////////////////////
                    //多边形逼近
                    //List<VectorOfPoint> results = new List<VectorOfPoint>();
                    //for (int i = 0; i < contours.Size; i++)
                    //{
                    //    var contour = contours[i];


                    //    VectorOfPoint approxContour = new VectorOfPoint();
                    //    CvInvoke.ApproxPolyDP(contour, approxContour, 0.5, true);
                    //    results.Add(approxContour);

                    //    count1 += contour.Size;
                    //    count2 += approxContour.Size;

                    //    CvInvoke.Dilate(contour, contour,);
                    //}



                    var list = contours.ToArrayOfArray().Select(v => new Contour {
                        Pts = v
                    }).OrderByDescending(v => v.Pts.Length).ToList();
                    //var list = results.Select(v => new Contour { Pts = v.ToArray() }).OrderByDescending(v => v.Pts.Length).ToList();
                    Contours Cons = new Contours();
                    Cons.Items  = list;
                    Cons.Width  = img.Width;
                    Cons.Height = img.Height;

                    return(Cons);
                }
        }
        /// <summary>
        /// Rozpoznaje pionki na planszy. Przed wywołaniem należy wywołać funkcję RozpoznajPola.
        /// </summary>
        /// <returns>Zwraca pozycje pionków na warcabnicy. Jeśli nie wywołano funkcji RozpoznajPola lub zwróciła ona inną wartość niż 32, funkcja zwraca null.</returns>
        public Pionek[] RozpoznajPionki()
        {
            if (Plansza == null)
            {
                return(null);
            }

            Mat obr = WczytajObraz();
            HashSet <Pionek> pionki = new HashSet <Pionek>();

            DanePionka[] dane = new DanePionka[] {
                new DanePionka()
                {
                    min = pionki_min, max = pionki_max, typ = TypObiektu.Pionki
                },
                new DanePionka()
                {
                    min = damki_min, max = damki_max, typ = TypObiektu.Damki
                },
                new DanePionka()
                {
                    min = pionki_wrog_min, max = pionki_wrog_max, typ = TypObiektu.PionkiWrog
                },
                new DanePionka()
                {
                    min = damki_wrog_min, max = damki_wrog_max, typ = TypObiektu.DamkiWrog
                }
            };

            for (int d = 0; d < dane.Length; d++)
            {
                VectorOfVectorOfPoint kontury = new VectorOfVectorOfPoint();
                Mat wyciety = new Mat();
                AnalizujPlansze(obr, dane[d].min, dane[d].max, ref kontury, ref wyciety);

                Point[][] punkty = kontury.ToArrayOfArray();
                Pole      pole;
                Point     srodek;
                Pole      pp;
                bool      znaleziono;

                for (int i = 0; i < punkty.Length; i++)
                {
                    pole       = new Pole(punkty[i].Min(p => p.X), punkty[i].Max(p => p.X), punkty[i].Min(p => p.Y), punkty[i].Max(p => p.Y));
                    srodek     = new Point(pole.xmin + (pole.xmax - pole.xmin) / 2, pole.ymin + (pole.ymax - pole.ymin) / 2);
                    znaleziono = false;

                    for (int x = 0; x < POLA_WIERSZ; x++)
                    {
                        for (int y = 0; y < POLA_WIERSZ; y++)
                        {
                            pp = Plansza[x, y];

                            if (pp.xmin < srodek.X && pp.xmax > srodek.X && pp.ymin < srodek.Y && pp.ymax > srodek.Y)
                            {
                                pionki.Add(new Pionek()
                                {
                                    x = x, y = y, typ = dane[d].typ
                                });
                                znaleziono = true;
                                break;
                            }
                        }

                        if (znaleziono)
                        {
                            break;
                        }
                    }
                }
            }

            return(pionki.ToArray());
        }
        /// <summary>
        /// Rozpoznaje białe pola na warcabnicy.
        /// </summary>
        /// <returns>Ilość rozpoznanych pól.</returns>
        public int RozpoznajPola()
        {
            Mat obr = WczytajObraz();
            VectorOfVectorOfPoint kontury = new VectorOfVectorOfPoint();
            Mat wyciety = new Mat();

            AnalizujPlansze(obr, pola_min, pola_max, ref kontury, ref wyciety);

            if (kontury.Size != ILOSC_POL_KOLOR)
            {
                Plansza = null;
                return(kontury.Size);
            }

            Point[][] punkty       = kontury.ToArrayOfArray();
            Pole[]    biale        = new Pole[punkty.Length];
            int       srednia_szer = 0;
            int       srednia_wys  = 0;
            Pole      pole;

            Point[] pola = new Point[ILOSC_POL];

            //Oblicz srednie rozmiary pol bialych
            for (int i = 0; i < punkty.Length; i++)
            {
                pole          = new Pole(punkty[i].Min(p => p.X), punkty[i].Max(p => p.X), punkty[i].Min(p => p.Y), punkty[i].Max(p => p.Y));
                biale[i]      = pole;
                srednia_szer += pole.xmax - pole.xmin;
                srednia_wys  += pole.ymax - pole.ymin;
            }

            srednia_szer /= punkty.Length;
            srednia_wys  /= punkty.Length;

            //Wyznacz granice pol
            biale = biale.OrderBy(p => p.ymin).ToArray();
            Pole plansza_rozm = new Pole(biale.Min(p => p.xmin), biale.Max(p => p.xmax), biale.Min(p => p.ymin), biale.Max(p => p.ymax));

            Plansza = new Pole[POLA_WIERSZ, POLA_WIERSZ];
            int ixw = 0;
            int ixk = 0;

            for (int i = 0; i < biale.Length; i += 4)
            {
                Pole[] wiersz = new Pole[POLA_WIERSZ_KOLOR];
                for (int j = 0; j < POLA_WIERSZ_KOLOR; j++)
                {
                    wiersz[j] = biale[i + j];
                }
                wiersz = wiersz.OrderBy(p => p.xmin).ToArray();

                if (wiersz[0].xmin > (plansza_rozm.xmin + srednia_szer))      //W wierszu najpierw czarne
                {
                    Plansza[0, ixk] = new Pole(plansza_rozm.xmin, wiersz[0].xmin, wiersz[0].ymin, wiersz[0].ymax, KolorPola.czarne);

                    ixw = 1;
                    for (int j = 0; j < POLA_WIERSZ_KOLOR; j++)
                    {
                        Plansza[ixw, ixk] = new Pole(wiersz[j], KolorPola.biale);
                        ixw++;
                        if (j != POLA_WIERSZ_KOLOR - 1)
                        {
                            Plansza[ixw, ixk] = new Pole(wiersz[j].xmax, wiersz[j + 1].xmin, wiersz[j].ymin, wiersz[j].ymax, KolorPola.czarne);
                            ixw++;
                        }
                    }
                }
                else        //W wierszu najpierw biale
                {
                    ixw = 0;
                    for (int j = 0; j < POLA_WIERSZ_KOLOR; j++)
                    {
                        Plansza[ixw, ixk] = new Pole(wiersz[j], KolorPola.biale);
                        ixw++;
                        if (j != POLA_WIERSZ_KOLOR - 1)
                        {
                            Plansza[ixw, ixk] = new Pole(wiersz[j].xmax, wiersz[j + 1].xmin, wiersz[j].ymin, wiersz[j].ymax, KolorPola.czarne);
                            ixw++;
                        }
                    }

                    Plansza[7, ixk] = new Pole(wiersz[3].xmax, plansza_rozm.xmax, wiersz[3].ymin, wiersz[3].ymax, KolorPola.czarne);
                }

                ixk++;
            }

            return(punkty.Length);
        }
示例#28
0
        private void button7_Click(object sender, EventArgs e)
        {
            var image = (Image <Gray, Single>)imageBox1.Image;
            Image <Gray, Byte>    image2 = image.Convert <Gray, Byte>();
            VectorOfVectorOfPoint con    = new VectorOfVectorOfPoint();
            Image <Gray, byte>    c      = new Image <Gray, byte>(image.Width, image.Height);

            CvInvoke.FindContours(image2, con, c, RetrType.External, ChainApproxMethod.ChainApproxNone);
            Point[][]  con1 = con.ToArrayOfArray();
            PointF[][] con2 = Array.ConvertAll <Point[], PointF[]>(con1, new Converter <Point[], PointF[]>(PointToPointF));
            int        k    = 1;

            for (int i = 0; i < con.Size; i++)
            {
                CvInvoke.DrawContours(img, con, i, new MCvScalar(255, 0, 255, 255), 2);
                RotatedRect rrec    = CvInvoke.MinAreaRect(con2[i]);
                PointF[]    pointfs = rrec.GetVertices();
                if (verifySize(rrec))
                {
                    for (int j = 0; j < pointfs.Length; j++)
                    {
                        CvInvoke.Line(img, new Point((int)pointfs[j].X, (int)pointfs[j].Y), new Point((int)pointfs[(j + 1) % 4].X, (int)pointfs[(j + 1) % 4].Y), new MCvScalar(0, 255, 0, 255), 4);
                        float r         = rrec.Size.Width / rrec.Size.Height;
                        float angle     = rrec.Angle;
                        SizeF rect_size = rrec.Size;
                        Size  rectsize  = rect_size.ToSize();
                        if (r < 1)
                        {
                            angle = 90 + angle;
                            float a = rect_size.Width;
                            rect_size.Width  = rect_size.Height;
                            rect_size.Height = a;
                        }
                        if (angle - m_angle < 0 && angle + m_angle > 0)
                        {
                            Mat img_rotated = new Mat();
                            Mat rotmat      = new Mat();
                            Mat resultMat   = new Mat();
                            CvInvoke.GetRotationMatrix2D(rrec.Center, angle, 1, rotmat);
                            CvInvoke.WarpAffine(img, img_rotated, rotmat, img.Size, Inter.Cubic);
                            CvInvoke.Imshow("img_rotated", img_rotated);
                            PointF recCenterF = rrec.Center;

                            resultMat = showResultMat(img_rotated, rectsize, rrec.Center, k++);
                        }
                    }
                }
            }



            PointF[] PointToPointF(Point[] pf)
            {
                PointF[] aaa = new PointF[pf.Length];
                int      num = 0;

                foreach (var point in pf)
                {
                    aaa[num].X   = (int)point.X;
                    aaa[num++].Y = (int)point.Y;
                }
                return(aaa);
            }

            imageBox1.Image = img;


            //Image<Bgr, byte> a = img;
            //Image<Gray, byte> b = new Image<Gray, byte>(a.Width, a.Height);
            //Image<Gray, byte> c = new Image<Gray, byte>(a.Width, a.Height);
            //Image<Bgr, byte> d = new Image<Bgr, byte>(a.Width, a.Height);
            //CvInvoke.Canny(a, b, 100, 60);
            //VectorOfVectorOfPoint con = new VectorOfVectorOfPoint();
            //CvInvoke.FindContours(b, con, c, RetrType.External, ChainApproxMethod.ChainApproxNone);
            //for (int i = 0; i < con.Size; i++)
            //    CvInvoke.DrawContours(d, con, i, new MCvScalar(255, 0, 255, 255), 2);
            //imageBox1.Image = d;
        }
示例#29
0
        private void Application_Idle(object sender, EventArgs e)
        {
            Mat a = cap.QueryFrame();

            if (a != null)
            {
                System.Threading.Thread.Sleep((int)(1000.0 / fps - 5));
                imageBox1.Image = a;
                GC.Collect();
            }

            /*
             * Image<Bgr, byte> colorImage = new Image<Bgr, byte>(imageBox1.Image.Bitmap);
             * //取得灰階影像
             * Image<Gray, byte> grayImage = new Image<Gray, byte>(colorImage.Bitmap);
             * imageBox2.Image = grayImage;
             *
             *
             * //二值化的閥值
             * Gray thresholdValue = new Gray(55);
             * //取得二值化影像
             * Image<Gray, byte> thresholdImage = grayImage.ThresholdBinary(thresholdValue, new Gray(255));
             * //thresholdImage.Save("threshold.bmp");
             * imageBox3.Image = thresholdImage;*/
            if (a != null)
            {
                Image <Bgr, byte>  colorImage = new Image <Bgr, byte>(imageBox1.Image.Bitmap);
                Image <Gray, byte> b          = new Image <Gray, byte>(a.Width, a.Height);
                Image <Gray, byte> c          = new Image <Gray, byte>(a.Width, a.Height);
                Image <Bgr, byte>  d          = new Image <Bgr, byte>(a.Width, a.Height);
                Image <Gray, byte> abc        = new Image <Gray, byte>(a.Width, a.Height);
                CvInvoke.Canny(colorImage, b, 100, 60);
                VectorOfVectorOfPoint con = new VectorOfVectorOfPoint();
                CvInvoke.FindContours(b, con, c, RetrType.Ccomp, ChainApproxMethod.ChainApproxSimple);
                Point[][]  con1 = con.ToArrayOfArray();
                PointF[][] con2 = Array.ConvertAll <Point[], PointF[]>(con1, new Converter <Point[], PointF[]>(PointToPointF));
                for (int i = 0; i < con.Size; i++)
                {
                    PointF[] hull = CvInvoke.ConvexHull(con2[i], true);
                    for (int j = 0; j < hull.Length; j++)
                    {
                        Point p1 = new Point((int)(hull[j].X + 0.5), (int)(hull[j].Y + 0.5));
                        Point p2;
                        if (j == hull.Length - 1)
                        {
                            p2 = new Point((int)(hull[0].X + 0.5), (int)(hull[0].Y + 0.5));
                        }
                        else
                        {
                            p2 = new Point((int)(hull[j + 1].X + 0.5), (int)(hull[j + 1].Y + 0.5));
                        }
                        CvInvoke.Circle(abc, p1, 3, new MCvScalar(0, 255, 255, 255), 6);
                        CvInvoke.Line(abc, p1, p2, new MCvScalar(255, 255, 0, 255), 3);
                    }
                }
                for (int i = 0; i < con.Size; i++)
                {
                    CvInvoke.DrawContours(d, con, i, new MCvScalar(255, 0, 255, 255), 2);
                }
                imageBox2.Image = d;
                imageBox3.Image = abc;
            }
        }
示例#30
0
        private Dictionary <int, KeyValuePair <decimal, decimal> > _FindContoursAndCalculate(Emgu.CV.Image <Bgr, Byte> colorImage, out Emgu.CV.Image <Gray, Byte> processedImage)
        {
            int circles = 0;
            VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
            Mat hierarchy = new Mat();

            /// Detect edges using Threshold
            Image <Gray, Byte> Img_Source_Gray = colorImage.Convert <Gray, Byte>();

            Img_Source_Gray = Img_Source_Gray.SmoothBlur(3, 3);
            Image <Gray, Byte> threshold_output = Img_Source_Gray.ThresholdBinary(new Gray(90), new Gray(255));

            /// Find contours
            CvInvoke.FindContours(threshold_output, contours, hierarchy, RetrType.Tree, ChainApproxMethod.ChainApproxSimple);
            /// Approximate contours to polygons + get bounding rects and circles
            VectorOfVectorOfPoint contours_poly = new VectorOfVectorOfPoint(contours.Size);

            Point[][]  con  = contours.ToArrayOfArray();
            PointF[][] conf = new PointF[con.GetLength(0)][];
            for (int i = 0; i < con.GetLength(0); i++)
            {
                conf[i] = new PointF[con[i].Length];
                for (int j = 0; j < con[i].Length; j++)
                {
                    conf[i][j] = new PointF(con[i][j].X, con[i][j].Y);
                }
            }


            for (int i = 0; i < contours.Size; i++)
            {
                double a = CvInvoke.ContourArea(contours[i], false);
                if (a > 30000)
                {
                    CvInvoke.ApproxPolyDP(contours[i], contours_poly[circles], 3, true);

                    circles++;
                }
            }

            /// Draw polygonal contour + bonding rects + circles
            Image <Gray, byte> filteredImage = new Image <Gray, byte>(Img_Source_Gray.Width, Img_Source_Gray.Height);

            for (int i = 0; i < circles; i++)
            {
                CvInvoke.DrawContours(filteredImage, contours_poly, i, new MCvScalar(255, 255, 255), -1);
            }


            filteredImage = colorImage.Convert <Gray, Byte>().And(filteredImage);
            Image <Gray, Byte>    whiteAreas      = new Image <Gray, byte>(filteredImage.Width, filteredImage.Height);
            List <DetectedCircle> detectedCircles = new List <DetectedCircle>();

            for (int i = 0; i < circles; i++)
            {
                PointF[]       pointfs        = Array.ConvertAll(contours_poly[i].ToArray(), input => new PointF(input.X, input.Y));
                Rectangle      boundingRect   = PointCollection.BoundingRectangle(pointfs);
                DetectedCircle detectedCircle = new DetectedCircle()
                {
                    contour = contours_poly[i], boundingRect = boundingRect, center = new Point(boundingRect.X + (boundingRect.Width / 2), boundingRect.Y + (boundingRect.Height / 2))
                };
                detectedCircles.Add(detectedCircle);
                filteredImage.ROI = boundingRect;
                int threshold = _ComputeThreshold(filteredImage, detectedCircle);
                filteredImage.ROI = Rectangle.Empty;
                Image <Gray, Byte> mask = new Image <Gray, byte>(filteredImage.Width, filteredImage.Height);
                mask.Draw(boundingRect, new Gray(255), -1);
                mask = filteredImage.And(mask);
                /* Extract white are solely based on the Blue channel */
                mask       = mask.ThresholdBinary(new Gray(threshold), new Gray(255));
                whiteAreas = whiteAreas.Or(mask.Convert <Gray, Byte>().ThresholdBinary(new Gray(10), new Gray(255)));
                CvInvoke.DrawContours(whiteAreas, contours_poly, i, new MCvScalar(255, 255, 255), 3);
            }


            detectedCircles = detectedCircles.OrderBy(c => c.center.X).ToList();
            processedImage  = whiteAreas;
            return(_ComputeMetrics(whiteAreas, detectedCircles, circles));
        }