Example #1
0
        /// <summary>
        /// Calculates area of a polygonal contour. 
        /// </summary>
        /// <param name="p">Contour (polygon type).</param>
        /// <returns>Area of the contour.</returns>
        public static double ContourPolygonArea(CvContourPolygon p)
        {
            if (p == null)
                throw new ArgumentNullException("p");

            return CvBlobInvoke.cvb_cvContourPolygonArea(p.CvPtr);
        }
Example #2
0
        public IplImage BlobContourImage(IplImage src)
        {
            blobcontour = new IplImage(src.Size, BitDepth.U8, 3);
            bin         = this.Binary(src, 50);

            CvBlobs blobs = new CvBlobs();

            blobs.Label(bin);

            foreach (KeyValuePair <int, CvBlob> item in blobs)
            {
                CvBlob b = item.Value;

                CvContourChainCode cc = b.Contour;
                cc.Render(blobcontour);

                CvContourPolygon ex_polygon = cc.ConvertToPolygon();
                foreach (CvPoint p in ex_polygon)
                {
                    Cv.DrawCircle(blobcontour, p, 1, CvColor.Blue, -1);
                }

                for (int i = 0; i < b.InternalContours.Count; i++)
                {
                    CvContourPolygon in_polygon = b.InternalContours[i].ConvertToPolygon();
                    foreach (CvPoint p in in_polygon)
                    {
                        Cv.DrawCircle(blobcontour, p, 1, CvColor.Red, -1);
                    }
                }
            }
            return(blobcontour);
        }
Example #3
0
        /// <summary>
        /// Convert a chain code contour to a polygon.
        /// </summary>
        /// <returns>A polygon.</returns>
        public CvContourPolygon ConvertToPolygon()
        {
            CvContourPolygon contour = new CvContourPolygon();

            int x = StartingPoint.X;
            int y = StartingPoint.Y;
            contour.Add(new Point(x, y));

            if (ChainCode.Count > 0)
            {
                CvChainCode lastCode = ChainCode[0];
                x += CvBlobConst.ChainCodeMoves[(int) ChainCode[0]][0];
                y += CvBlobConst.ChainCodeMoves[(int) ChainCode[0]][1];
                for (int i = 1; i < ChainCode.Count; i++)
                {
                    if (lastCode != ChainCode[i])
                    {
                        contour.Add(new Point(x, y));
                        lastCode = ChainCode[i];
                    }
                    x += CvBlobConst.ChainCodeMoves[(int) ChainCode[i]][0];
                    y += CvBlobConst.ChainCodeMoves[(int) ChainCode[i]][1];
                }
            }

            return contour;
        }
Example #4
0
        public int[] 点数計算(Mat 検査結果, Mat テンプレート, int[,] 正解座標)
        {
            int score        = 0;
            var result_clone = 検査結果.Clone();

            paint_black(ref result_clone, テンプレート);

            CvBlobs blobs = new CvBlobs(result_clone);

            blobs.FilterByArea(9, 250);

            int[,] 正解座標2 = (int[, ])正解座標.Clone();
            int 正解数  = 0;
            int 正解数  = 0;
            int 許容回数 = 5;
            int 未検出数 = 0;

            foreach (CvBlob item in blobs.Values)
            {
                CvContourPolygon polygon = item.Contour.ConvertToPolygon();
                Point2f          circleCenter;
                float            circleRadius;

                GetEnclosingCircle(polygon, out circleCenter, out circleRadius);
                for (int j = 0; j < 正解座標2.Length / 2; j++)
                {
                    if (正解座標2[j, 0] != 0 && (Math.Pow(circleCenter.X - 正解座標2[j, 0], 2) + Math.Pow(circleCenter.Y - 正解座標2[j, 1], 2) < circleRadius * circleRadius))
                    {//外接円内にあったら
                        正解数++;
                        正解座標2[j, 0] = 正解座標2[j, 1] = 0;
                        j           = 正解座標2.Length;//ひとつ照合確定したら,このfor文を抜けて次のラベルの検査に移動
                    }
                }
            }

            for (int i = 0; i < 正解座標2.Length / 2; i++)
            {//検出されなかった座標が残る
                if (正解座標2[i, 0] != 0)
                {
                    未検出数++;
                }
            }

            正解数 = blobs.Count - 正解数;

            if (正解数 <= 許容回数)
            {
                score = (int)((float)(正解数) * (10000.0f / (正解座標.Length / 2)));
            }
            else
            {
                score = (int)((float)(正解数 - (正解数 - 許容回数)) * (10000.0f / (正解座標.Length / 2)));
            }

            blobs        = null;
            result_clone = null;

            return(new int[] { score, 正解数, 未検出数 });
        }
Example #5
0
        public void 点数計算_debug(CvBlobs blobs, int[,] 正解座標, ref Mat color)
        {
            if (正解座標 != null)
            {
                int[,] 正解座標2 = (int[, ])正解座標.Clone();
                int 正解数   = 0;
                int 正解数   = 0;
                int 許容回数  = 5;
                int 未検出数  = 0;
                int score = 0;

                foreach (CvBlob item in blobs.Values)
                {
                    CvContourPolygon polygon = item.Contour.ConvertToPolygon();
                    Point2f          circleCenter;
                    float            circleRadius;

                    GetEnclosingCircle(polygon, out circleCenter, out circleRadius);
                    for (int j = 0; j < 正解座標2.Length / 2; j++)
                    {
                        if (正解座標2[j, 0] != 0 && (Math.Pow(circleCenter.X - 正解座標2[j, 0], 2) + Math.Pow(circleCenter.Y - 正解座標2[j, 1], 2) < circleRadius * circleRadius))
                        {//外接円内にあったら
                            Cv2.Circle(color, item.Centroid, (int)circleRadius, new Scalar(0, 0, 255), 2);
                            正解数++;
                            正解座標2[j, 0] = 正解座標2[j, 1] = 0;
                            j           = 正解座標2.Length;//ひとつ照合確定したら,このfor文を抜けて次のラベルの検査に移動
                        }
                    }
                }

                System.Diagnostics.Debug.WriteLine("未検出座標");
                for (int i = 0; i < 正解座標2.Length / 2; i++)
                {//検出されなかった座標が残る
                    if (正解座標2[i, 0] != 0)
                    {
                        System.Diagnostics.Debug.WriteLine(i + ":" + 正解座標2[i, 0] + "," + 正解座標2[i, 1]);
                        未検出数++;
                    }
                }

                正解数 = blobs.Count - 正解数;
                if (正解数 <= 許容回数)
                {
                    score = (int)((float)(正解数) * (10000.0f / (正解座標.Length / 2)));
                }
                else
                {
                    score = (int)((float)(正解数 - (正解数 - 許容回数)) * (10000.0f / (正解座標.Length / 2)));
                }

                Cv2.PutText(color, "score= " + score.ToString(), new Point(10, 120), HersheyFonts.HersheySimplex, 1, new Scalar(0, 0, 0));
                Cv2.PutText(color, "unCorrect= " + 正解数.ToString(), new Point(10, 140), HersheyFonts.HersheySimplex, 1, new Scalar(0, 0, 0));
                Cv2.PutText(color, "unFind= " + 未検出数.ToString(), new Point(10, 160), HersheyFonts.HersheySimplex, 1, new Scalar(0, 0, 0));
            }
        }
Example #6
0
    // Update is called once per frame
    void Update()
    {
        IplImage frame = Cv.QueryFrame(capture);

        imgBinary  = new IplImage(frame.Size, BitDepth.U8, 1);
        imgLabel   = new IplImage(frame.Size, BitDepth.F32, 1);
        imgRender  = new IplImage(frame.Size, BitDepth.U8, 3);
        imgContour = new IplImage(frame.Size, BitDepth.U8, 3);
        imgPolygon = new IplImage(frame.Size, BitDepth.U8, 3);
        Color[] cols = new Color[texture.width * texture.height];
        Cv.CvtColor(frame, imgBinary, ColorConversion.BgrToGray);
        Cv.Threshold(imgBinary, imgBinary, 100, 255, ThresholdType.Binary);
        CvBlobs blobs  = new CvBlobs();
        uint    result = blobs.Label(imgBinary, imgLabel);

        foreach (KeyValuePair <uint, CvBlob> item in blobs)
        {
            CvBlob b = item.Value;
            //Console.WriteLine ("{0} | Centroid:{1} Area:{2}", item.Key, b.Centroid, b.Area);

            CvContourChainCode cc = b.Contour;
            cc.RenderContourChainCode(imgContour);

            CvContourPolygon polygon = cc.ConvertChainCodesToPolygon();
            foreach (CvPoint p in polygon)
            {
                imgPolygon.Circle(p, 1, CvColor.Red, -1);
            }
        }

        blobs.RenderBlobs(imgLabel, frame, imgRender);

        for (int y = 0; y < texture.height; y++)
        {
            for (int x = 0; x < texture.width; x++)
            {
                CvColor col = imgRender.Get2D(y, x);
                cols[y * texture.width + x] = new Color(col.R / 255.0f, col.G / 255.0f, col.B / 255.0f, 1.0f);
            }
        }
        // int t2 = System.Environment.TickCount;
        texture.SetPixels(cols);
        //int t3 = System.Environment.TickCount;
        //Debug.Log("t2-t1=" + (t2 - t1) + " t3-t2=" + (t3 - t2));
        texture.Apply();
    }
Example #7
0
        public Blob()
        {
            using (var imgSrc = new IplImage(FilePath.Image.Shapes, LoadMode.Color))
                using (var imgBinary = new IplImage(imgSrc.Size, BitDepth.U8, 1))
                    using (var imgRender = new IplImage(imgSrc.Size, BitDepth.U8, 3))
                        using (var imgContour = new IplImage(imgSrc.Size, BitDepth.U8, 3))
                            using (var imgPolygon = new IplImage(imgSrc.Size, BitDepth.U8, 3))
                            {
                                Cv.CvtColor(imgSrc, imgBinary, ColorConversion.BgrToGray);
                                Cv.Threshold(imgBinary, imgBinary, 100, 255, ThresholdType.Binary);

                                CvBlobs blobs = new CvBlobs();
                                blobs.Label(imgBinary);

                                foreach (KeyValuePair <int, CvBlob> item in blobs)
                                {
                                    CvBlob b = item.Value;
                                    Console.WriteLine("{0} | Centroid:{1} Area:{2}", item.Key, b.Centroid, b.Area);

                                    CvContourChainCode cc = b.Contour;
                                    cc.Render(imgContour);

                                    CvContourPolygon polygon = cc.ConvertToPolygon();
                                    foreach (CvPoint p in polygon)
                                    {
                                        imgPolygon.Circle(p, 1, CvColor.Red, -1);
                                    }

                                    /*
                                     * CvPoint2D32f circleCenter;
                                     * float circleRadius;
                                     * GetEnclosingCircle(polygon, out circleCenter, out circleRadius);
                                     * imgPolygon.Circle(circleCenter, (int) circleRadius, CvColor.Green, 2);
                                     */
                                }

                                blobs.RenderBlobs(imgSrc, imgRender);

                                using (new CvWindow("render", imgRender))
                                    using (new CvWindow("contour", imgContour))
                                        using (new CvWindow("polygon vertices", imgPolygon))
                                        {
                                            Cv.WaitKey(0);
                                        }
                            }
        }
Example #8
0
        public Blob()
        {
            using (IplImage imgSrc = new IplImage(Const.ImageShapes, LoadMode.Color))
                using (IplImage imgBinary = new IplImage(imgSrc.Size, BitDepth.U8, 1))
                    using (IplImage imgLabel = new IplImage(imgSrc.Size, BitDepth.F32, 1))
                        using (IplImage imgRender = new IplImage(imgSrc.Size, BitDepth.U8, 3))
                            using (IplImage imgContour = new IplImage(imgSrc.Size, BitDepth.U8, 3))
                                using (IplImage imgPolygon = new IplImage(imgSrc.Size, BitDepth.U8, 3))
                                {
                                    Cv.CvtColor(imgSrc, imgBinary, ColorConversion.BgrToGray);
                                    Cv.Threshold(imgBinary, imgBinary, 100, 255, ThresholdType.Binary);

                                    CvBlobs blobs = new CvBlobs();
                                    blobs.Label(imgBinary);

                                    foreach (KeyValuePair <int, CvBlob> item in blobs)
                                    {
                                        CvBlob b = item.Value;
                                        Console.WriteLine("{0} | Centroid:{1} Area:{2}", item.Key, b.Centroid, b.Area);

                                        CvContourChainCode cc = b.Contour;
                                        cc.Render(imgContour);

                                        CvContourPolygon polygon = cc.ConvertToPolygon();
                                        foreach (CvPoint p in polygon)
                                        {
                                            imgPolygon.Circle(p, 1, CvColor.Red, -1);
                                        }
                                    }

                                    blobs.RenderBlobs(imgSrc, imgRender);

                                    using (new CvWindow("render", imgRender))
                                        using (new CvWindow("contour", imgContour))
                                            using (new CvWindow("polygon vertices", imgPolygon))
                                            {
                                                Cv.WaitKey(0);
                                            }
                                }
        }
Example #9
0
 /// <summary>
 /// Write a contour to a SVG file.
 /// </summary>
 /// <param name="polygon">Polygon contour.</param>
 /// <param name="fileName">File name.</param>
 public static void WriteContourPolygonSvg(CvContourPolygon polygon, string fileName)
 {
     polygon.WriteAsSvg(fileName);
 }
Example #10
0
 /// <summary>
 /// Write a contour to a SVG file.
 /// </summary>
 /// <param name="p">Polygon contour.</param>
 /// <param name="filename">File name.</param>
 public static void WriteContourPolygonSVG(CvContourPolygon p, string filename)
 {
     WriteContourPolygonSVG(p, filename, CvColor.Black, CvColor.White);
 }
Example #11
0
 /// <summary>
 /// Simplify a polygon reducing the number of vertex according the distance "delta". 
 /// Uses a version of the Ramer-Douglas-Peucker algorithm (http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm). 
 /// </summary>
 /// <param name="p">Contour (polygon type).</param>
 /// <returns>A simplify version of the original polygon.</returns>
 public static CvContourPolygon SimplifyPolygon(CvContourPolygon p)
 {
     return SimplifyPolygon(p, 1.0);
 }
Example #12
0
 /// <summary>
 /// Draw a polygon.
 /// </summary>
 /// <param name="contour">Polygon contour.</param>
 /// <param name="img">Image to draw on.</param>
 public static void RenderContourPolygon(CvContourPolygon contour, IplImage img)
 {
     RenderContourPolygon(contour, img, new CvScalar(255, 255, 255, 0));
 }
Example #13
0
 /// <summary>
 /// Calculates perimeter of a chain code contour.
 /// </summary>
 /// <param name="polygon">Contour (polygon type).</param>
 /// <returns>Perimeter of the contour.</returns>
 public static double ContourPolygonPerimeter(CvContourPolygon polygon)
 {
     if (polygon == null)
         throw new ArgumentNullException(nameof(polygon));
     return polygon.Perimeter();
 }
Example #14
0
 /// <summary>
 /// Draw a polygon.
 /// </summary>
 /// <param name="contour">Polygon contour.</param>
 /// <param name="img">Image to draw on.</param>
 /// <param name="color">Color to draw (default, white).</param>
 public static void RenderContourPolygon(CvContourPolygon contour, IplImage img, CvScalar color)
 {
     if (contour == null)
         throw new ArgumentNullException("contour");
     contour.Render(img, color);
 }
Example #15
0
 /// <summary>
 /// Draw a polygon.
 /// </summary>
 /// <param name="contour">Polygon contour.</param>
 /// <param name="img">Image to draw on.</param>
 public static void RenderContourPolygon(CvContourPolygon contour, Mat img)
 {
     if (contour == null)
         throw new ArgumentNullException("contour");
     contour.Render(img);
 }
Example #16
0
 /// <summary>
 /// Write a contour to a SVG file.
 /// </summary>
 /// <param name="polygon">Polygon contour.</param>
 /// <param name="fileName">File name.</param>
 /// <param name="stroke">Stroke color (black by default).</param>
 /// <param name="fill">Fill color (white by default).</param>
 public static void WriteContourPolygonSvg(CvContourPolygon polygon, string fileName,
     Scalar stroke, Scalar fill)
 {
     if (polygon == null)
         throw new ArgumentNullException(nameof(polygon));
     polygon.WriteAsSvg(fileName, stroke, fill);
 }
Example #17
0
 /// <summary>
 /// Calculates the circularity of a polygon (compactness measure).
 /// </summary>
 /// <param name="polygon">Contour (polygon type).</param>
 /// <returns>Circularity: a non-negative value, where 0 correspond with a circumference.</returns>
 public static double ContourPolygonCircularity(CvContourPolygon polygon)
 {
     if (polygon == null)
         throw new ArgumentNullException(nameof(polygon));
     return polygon.Circularity();
 }
Example #18
0
 /// <summary>
 /// Calculates area of a polygonal contour. 
 /// </summary>
 /// <param name="polygon">Contour (polygon type).</param>
 /// <returns>Area of the contour.</returns>
 public static double ContourPolygonArea(CvContourPolygon polygon)
 {
     if (polygon == null)
         throw new ArgumentNullException("polygon");
     return polygon.Area();
 }
Example #19
0
        /// <summary>
        /// Calculates convex hull of a contour.
        /// Uses the Melkman Algorithm. Code based on the version in http://w3.impa.br/~rdcastan/Cgeometry/.
        /// </summary>
        /// <param name="p">Contour (polygon type).</param>
        /// <returns>Convex hull.</returns>
        public static CvContourPolygon PolygonContourConvexHull(CvContourPolygon p)
        {
            if (p == null)
                throw new ArgumentNullException("p");

            IntPtr result = CvBlobInvoke.cvb_cvPolygonContourConvexHull(p.CvPtr);
            if (result == IntPtr.Zero)
                return null;
            else
                return new CvContourPolygon(result);
        }
Example #20
0
 /// <summary>
 /// Calculates convex hull of a contour.
 /// Uses the Melkman Algorithm. Code based on the version in http://w3.impa.br/~rdcastan/Cgeometry/.
 /// </summary>
 /// <param name="polygon">Contour (polygon type).</param>
 /// <returns>Convex hull.</returns>
 public static CvContourPolygon PolygonContourConvexHull(CvContourPolygon polygon)
 {
     if (polygon == null)
         throw new ArgumentNullException(nameof(polygon));
     return polygon.ContourConvexHull();
 }
Example #21
0
 /// <summary>
 /// Draw a polygon.
 /// </summary>
 /// <param name="contour">Polygon contour.</param>
 /// <param name="img">Image to draw on.</param>
 /// <param name="color">Color to draw (default, white).</param>
 public static void RenderContourPolygon(CvContourPolygon contour, IplImage img, CvScalar color)
 {
     if (contour == null)
         throw new ArgumentNullException("contour");
     if (img == null)
         throw new ArgumentNullException("img");
     CvBlobInvoke.cvb_cvRenderContourPolygon(contour.CvPtr, img.CvPtr, color);
 }
Example #22
0
 /// <summary>
 /// Draw a polygon.
 /// </summary>
 /// <param name="contour">Polygon contour.</param>
 /// <param name="img">Image to draw on.</param>
 /// <param name="color">Color to draw (default, white).</param>
 public static void RenderContourPolygon(CvContourPolygon contour, Mat img, Scalar color)
 {
     if (contour == null)
         throw new ArgumentNullException(nameof(contour));
     contour.Render(img, color);
 }
Example #23
0
        /// <summary>
        /// Simplify a polygon reducing the number of vertex according the distance "delta". 
        /// Uses a version of the Ramer-Douglas-Peucker algorithm (http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm). 
        /// </summary>
        /// <param name="p">Contour (polygon type).</param>
        /// <param name="delta">Minimun distance.</param>
        /// <returns>A simplify version of the original polygon.</returns>
        public static CvContourPolygon SimplifyPolygon(CvContourPolygon p, double delta)
        {
            if (p == null)
                throw new ArgumentNullException("p");

            IntPtr result = CvBlobInvoke.cvb_cvSimplifyPolygon(p.CvPtr, delta);
            if (result == IntPtr.Zero)
                return null;
            else
                return new CvContourPolygon(result);
        }
Example #24
0
 /// <summary>
 /// Simplify a polygon reducing the number of vertex according the distance "delta". 
 /// Uses a version of the Ramer-Douglas-Peucker algorithm (http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm). 
 /// </summary>
 /// <param name="polygon">Contour (polygon type).</param>
 /// <returns>A simplify version of the original polygon.</returns>
 public static CvContourPolygon SimplifyPolygon(CvContourPolygon polygon)
 {
     return polygon.Simplify();
 }
Example #25
0
 /// <summary>
 /// Write a contour to a SVG file.
 /// </summary>
 /// <param name="p">Polygon contour.</param>
 /// <param name="filename">File name.</param>
 /// <param name="stroke">Stroke color (black by default).</param>
 /// <param name="fill">Fill color (white by default).</param>
 public static void WriteContourPolygonSVG(CvContourPolygon p, string filename, CvScalar stroke, CvScalar fill)
 {
     if (p == null)
         throw new ArgumentNullException("p");
     if (string.IsNullOrEmpty(filename))
         throw new ArgumentNullException("filename");
     CvBlobInvoke.cvb_cvWriteContourPolygonSVG(p.CvPtr, filename, stroke, fill);
 }
Example #26
0
 /// <summary>
 /// Simplify a polygon reducing the number of vertex according the distance "delta". 
 /// Uses a version of the Ramer-Douglas-Peucker algorithm (http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm). 
 /// </summary>
 /// <param name="polygon">Contour (polygon type).</param>
 /// <param name="delta">Minimun distance.</param>
 /// <returns>A simplify version of the original polygon.</returns>
 public static CvContourPolygon SimplifyPolygon(CvContourPolygon polygon, double delta)
 {
     if (polygon == null)
         throw new ArgumentNullException(nameof(polygon));
     return polygon.Simplify(delta);
 }
Example #27
0
 /// <summary>
 /// Write a contour to a CSV (Comma-separated values) file.
 /// </summary>
 /// <param name="polygon">Polygon contour.</param>
 /// <param name="filename">File name.</param>
 public static void WriteContourPolygonCsv(CvContourPolygon polygon, string filename)
 {
     if (polygon == null)
         throw new ArgumentNullException(nameof(polygon));
     polygon.WriteAsCsv(filename);
 }
Example #28
0
        /// <summary>
        /// Takes blobs information based on colors in <see cref="hsv"/> list and then sends the info through UDP.
        /// </summary>
        /// <param name="sourceImage">Image in Mat format.</param>
        /// <returns>Image in Mat format.</returns>
        private Mat Renderer(Mat sourceImage)
        {
            Mat dstNoisy = src;
            Mat dstClear = new Mat();
            Mat dst      = new Mat();
            Mat element  = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(2 * MorphValue + 1, 2 * MorphValue + 1));

            Cv2.Blur(dstNoisy, dstClear, new Size(9, 9));

            Cv2.CvtColor(dstClear, dst, ColorConversionCodes.BGR2HSV); // Convert BGR to HSV.

            Mat dstThreshed = new Mat();
            Mat dstPreview  = new Mat();

            if (hsv.Count > 0)
            {
                int  blobCount = 1;
                bool theFirst  = true;

                foreach (int[] scal in hsv)
                {
                    if (theFirst)
                    {
                        Cv2.InRange(dst, new Scalar(scal[0] - 10, scal[1], scal[3]), new Scalar(scal[0] + 10, scal[2], scal[4]), dstPreview);
                        theFirst = false;
                    }
                    else
                    {
                        Mat dstPreview2 = new Mat();
                        Cv2.InRange(dst, new Scalar(scal[0] - 10, scal[1], scal[3]), new Scalar(scal[0] + 10, scal[2], scal[4]), dstPreview2);
                        Cv2.AddWeighted(dstThreshed, 1.0, dstPreview2, 1.0, 0.0, dstPreview);
                    }
                    Cv2.InRange(dst, new Scalar(scal[0] - 10, scal[1], scal[3]), new Scalar(scal[0] + 10, scal[2], scal[4]), dstThreshed);

                    // Morphologic transformation to close the gaps inside the blob.
                    Cv2.MorphologyEx(src: dstThreshed,
                                     dst: dstThreshed,
                                     op: MorphTypes.Close,
                                     element: element
                                     );

                    blobDetection.Label(dstThreshed);
                    blobDetection.FilterByArea(MinBlobArea, MaxBlobArea);
                    blobDetection.RenderBlobs(dstThreshed, src);
                    CircleSegment[] circles = Cv2.HoughCircles(dstThreshed, HoughMethods.Gradient, 1, dstThreshed.Rows / 8);

                    // Creates all udp datagrams----------------------------------------------------
                    if (blobDetection.Count != 0)
                    {
                        for (int i = 0; i < blobDetection.Count; i++)
                        {
                            int processKey = blobDetection.ElementAt(i).Key;
                            udpDatagram_1 = "[$]tracking|id=" + data_id + "|label=" + blobCount + "|[$$]" + deviceName + ",[$$$]mesh,sample,";
                            for (int j = 0; j < blobDetection[processKey].Contour.ConvertToPolygon().Simplify(1).Count; j++)
                            {
                                if (orientation)
                                {
                                    udpDatagram_1 += Math.Round((float)blobDetection[processKey].Contour.ConvertToPolygon().Simplify(1).ElementAt(j).X / dst.Cols, 4).ToString().Replace(',', '.');
                                    udpDatagram_1 += "," + (1 - Math.Round((float)blobDetection[processKey].Contour.ConvertToPolygon().Simplify(1).ElementAt(j).Y / dst.Rows, 4)).ToString().Replace(',', '.');
                                    udpDatagram_1 += ",";
                                }
                                else
                                {
                                    udpDatagram_1 += (1 - Math.Round((float)blobDetection[processKey].Contour.ConvertToPolygon().Simplify(1).ElementAt(j).X / dst.Cols, 4)).ToString().Replace(',', '.');
                                    udpDatagram_1 += "," + Math.Round((float)blobDetection[processKey].Contour.ConvertToPolygon().Simplify(1).ElementAt(j).Y / dst.Rows, 4).ToString().Replace(',', '.');
                                    udpDatagram_1 += ",";
                                }
                            }
                            udpDatagram_1 += ";";
                            udpDatagram_2  = "[$]tracking|id=" + data_id + "|label=" + blobCount + "|[$$]" + deviceName + ",[$$$]area,";
                            udpDatagram_2 += "value," + blobDetection[processKey].Contour.ConvertToPolygon().Simplify(1).Area().ToString().Replace(',', '.') + ";";
                            udpDatagram_3  = "[$]tracking|id=" + data_id + "|label=" + blobCount + "|[$$]" + deviceName + ",[$$$]place,";
                            if (orientation)
                            {
                                udpDatagram_3 += "position," + (Math.Round(blobDetection[processKey].Centroid.X / dst.Cols, 3)).ToString().Replace(',', '.') + "," + (Math.Round(1 - (blobDetection[processKey].Centroid.Y / dst.Rows), 3)).ToString().Replace(',', '.') + ";";
                            }
                            else
                            {
                                udpDatagram_3 += "position," + (Math.Round(1 - (blobDetection[processKey].Centroid.X / dst.Cols), 3)).ToString().Replace(',', '.') + "," + (Math.Round(blobDetection[processKey].Centroid.Y / dst.Rows, 3)).ToString().Replace(',', '.') + ";";
                            }
                            udpDatagram_4  = "[$]tracking|id=" + data_id + "|label=" + blobCount + "|[$$]" + deviceName + ",[$$$]color,";
                            udpDatagram_4 += "hsv," + scal[0] + "-" + (scal[1] + scal[2]) / 2 + "-" + (scal[3] + scal[4]) / 2 + ";";

                            //Geometry
                            udpDatagram_5 = "[$]tracking|id=" + data_id + "|label=" + blobCount + "|[$$]" + deviceName + ",[$$$]form,geometry,";
                            CvContourPolygon poly          = blobDetection[processKey].Contour.ConvertToPolygon();
                            double           epsilon       = 0.04 * Cv2.ArcLength(poly, true);
                            Point[]          counterResult = Cv2.ApproxPolyDP(poly, epsilon, closed: true);
                            int    contourSimple_counter   = counterResult.Length;
                            string geometry = "";
                            switch (contourSimple_counter)
                            {
                            case 3:
                                geometry = "triangle";
                                break;

                            case 4:
                                Rect  rect        = Cv2.BoundingRect(poly);
                                float aspectRatio = 0;
                                if (rect.Y != 0)
                                {
                                    aspectRatio = rect.X / rect.Y;
                                }
                                if (aspectRatio >= 0.95 && aspectRatio <= 1.05)
                                {
                                    geometry = "square";
                                }
                                else
                                {
                                    geometry = "rectangle";
                                }
                                break;

                            default:
                                geometry = "unidentified" + contourSimple_counter;
                                break;
                            }
                            udpDatagram_5 += geometry + ";";
                            if (BlobLabel)
                            {
                                Cv2.PutText(src, geometry, blobDetection[processKey].Centroid, HersheyFonts.HersheySimplex, 0.5, new Scalar(0, 255, 0), 2);
                                Cv2.PutText(src, "[" + scal[0] + ", " + ((scal[1] + scal[2]) / 2) + ", " + ((scal[3] + scal[4]) / 2) + "]", new Point(blobDetection[processKey].Centroid.X, blobDetection[processKey].Centroid.Y + 20), HersheyFonts.HersheySimplex, 0.45, new Scalar(0, 255, 0), 2);
                            }
                            udpDatagram_6  = "[$]tracking|id=" + data_id + "|label=" + blobCount + "|[$$]" + deviceName + ",[$$$]perimeter,value,";
                            udpDatagram_6 += blobDetection[processKey].Contour.Perimeter().ToString().Replace(',', '.') + ";";

                            // UDP sender---------------------------------------------------------------------
                            try
                            {
                                byte[] sendBytes_1 = Encoding.ASCII.GetBytes(udpDatagram_1);
                                byte[] sendBytes_2 = Encoding.ASCII.GetBytes(udpDatagram_2);
                                byte[] sendBytes_3 = Encoding.ASCII.GetBytes(udpDatagram_3);
                                byte[] sendBytes_4 = Encoding.ASCII.GetBytes(udpDatagram_4);
                                byte[] sendBytes_5 = Encoding.ASCII.GetBytes(udpDatagram_5);
                                byte[] sendBytes_6 = Encoding.ASCII.GetBytes(udpDatagram_6);
                                udpClient.Send(sendBytes_1, sendBytes_1.Length, IP_udp, Port_udp);
                                udpClient.Send(sendBytes_2, sendBytes_2.Length, IP_udp, Port_udp);
                                udpClient.Send(sendBytes_3, sendBytes_3.Length, IP_udp, Port_udp);
                                udpClient.Send(sendBytes_4, sendBytes_4.Length, IP_udp, Port_udp);
                                udpClient.Send(sendBytes_5, sendBytes_5.Length, IP_udp, Port_udp);
                                udpClient.Send(sendBytes_6, sendBytes_6.Length, IP_udp, Port_udp);
                            }
                            catch (Exception e)
                            {
                                Console.WriteLine(e.ToString());
                            }
                            udpDatagram_1 = "";
                            udpDatagram_2 = "";
                            udpDatagram_3 = "";
                            udpDatagram_4 = "";
                            blobCount++;
                        }
                    }
                }
                blobCount = 1;
            }

            // Same morphologic transformation but this time for the output image.
            Cv2.MorphologyEx(src: dstPreview,
                             dst: dstPreview,
                             op: MorphTypes.Close,
                             element: element
                             );

            return(dstPreview);
        }