/// <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); }
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); }
/// <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; }
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, 正解数, 未検出数 }); }
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)); } }
// 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(); }
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); } } }
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); } } }
/// <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); }
/// <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); }
/// <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); }
/// <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)); }
/// <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(); }
/// <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); }
/// <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); }
/// <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); }
/// <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(); }
/// <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(); }
/// <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); }
/// <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(); }
/// <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); }
/// <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); }
/// <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); }
/// <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(); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }