/// <summary> /// Return the ground truth ellipse's parameters from the CSV file. /// </summary> /// <param name="imageFilename">Filename of the image</param> /// <param name="csvFilepath">Filepath to the CSV file with ground truth ellipses' parameters</param> /// <returns>Ground truth ellipse's parameters</returns> private static GtEllipse GetGtEllipseFromCsv(string imageFilename, string csvFilepath) { using (StreamReader sr = new StreamReader(csvFilepath)) { GtEllipse gtEllipse; string line; sr.ReadLine(); // skip the header while ((line = sr.ReadLine()) != null) { string[] columns = line.Split(','); if (string.Compare(columns[0], imageFilename) == 0) { if (string.IsNullOrEmpty(columns[1])) { gtEllipse = null; } else { Point2f center = new Point2f(Convert.ToSingle(columns[1]), Convert.ToSingle(columns[2])); Size2f axes = new Size2f(Convert.ToSingle(columns[3]), Convert.ToSingle(columns[4])); float angle = Convert.ToSingle(columns[5]); Size imageSize = new Size(Convert.ToInt32(columns[6]), Convert.ToInt32(columns[7])); gtEllipse = new GtEllipse(center, axes, angle, imageSize); } return(gtEllipse); } ; } throw new Exception("Filename not found in the CSV file."); } }
static void EllipseEx(Texture2D img, Vector2 center, Size2f axes, int angle, int arc_start, int arc_end, Color color) { axes.width = Mathf.Abs(axes.width); axes.height = Mathf.Abs(axes.height); int delta = 5; List <Vector2> _v = ellipse2Poly(center, axes, angle, arc_start, arc_end, delta); List <Vector2Int> v = new List <Vector2Int>(); Vector2Int prevPt = new Vector2Int(0xFFFF, 0xFFFF); for (int i = 0; i < _v.Count; ++i) { Vector2Int pt = new Vector2Int(); pt.x = Mathf.RoundToInt(_v[i].x / XY_ONE) << XY_SHIFT; pt.y = Mathf.RoundToInt(_v[i].y / XY_ONE) << XY_SHIFT; pt.x += Mathf.RoundToInt(_v[i].x - pt.x); pt.y += Mathf.RoundToInt(_v[i].y - pt.y); if (pt != prevPt) { v.Add(pt); prevPt = pt; } } FillConvexPoly(img, v, v.Count, 0, color); }
void Canvas_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.PageUp) { ImageScale += ScaleIncrement; } if (e.KeyCode == Keys.PageDown) { ImageScale -= ScaleIncrement; } if (e.Control && e.KeyCode == Keys.Z) { commandExecutor.Undo(); } if (e.Control && e.KeyCode == Keys.Y) { commandExecutor.Redo(); } if (e.Control && e.KeyCode == Keys.V) { var roiText = (string)Clipboard.GetData(DataFormats.Text); try { var mousePosition = PointToClient(MousePosition); var offset = NormalizedLocation(mousePosition.X, mousePosition.Y); var roiData = (float[])ArrayConvert.ToArray(roiText, 1, typeof(float)); var center = new Point2f(offset.X, offset.Y); var size = new Size2f(roiData[0], roiData[1]); var roi = new RotatedRect(center, size, 0); var selection = selectedRoi; commandExecutor.Execute( () => AddRegion(roi), () => { regions.Remove(roi); SelectedRegion = selection; }); } catch (ArgumentException) { } catch (InvalidCastException) { } catch (FormatException) { } } if (selectedRoi.HasValue) { if (e.Control && e.KeyCode == Keys.C) { var roi = regions[selectedRoi.Value]; var roiData = new[] { roi.Size.Width, roi.Size.Height }; Clipboard.SetData(DataFormats.Text, ArrayConvert.ToString(roiData)); } if (e.KeyCode == Keys.Delete) { var selection = selectedRoi.Value; var region = regions[selection]; commandExecutor.Execute( () => { regions.RemoveAt(selection); SelectedRegion = null; }, () => { regions.Insert(selection, region); SelectedRegion = selection; }); } } }
public void Size2f() { var obj = new Size2f(0.5, 0.5); Assert.Equal(0.5, obj.Width, 6); Assert.Equal(0.5, obj.Height, 6); obj = new Size2f(0.5f, 0.5f); Assert.Equal(0.5f, obj.Width, 6); Assert.Equal(0.5f, obj.Height, 6); }
static RotatedRect ScaleRegion(RotatedRect region, Point target, bool uniformScaling) { var size = new Size2f( 2 * Math.Abs(target.X - region.Center.X), 2 * Math.Abs(target.Y - region.Center.Y)); if (uniformScaling) { var sizeNorm = (float)Math.Sqrt(size.Width * size.Width + size.Height * size.Height); region.Size.Width = sizeNorm; region.Size.Height = sizeNorm; } else { region.Size = size; } return(region); }
/// <summary> /// 旋转 /// </summary> /// <param name="image">图片对象</param> /// <param name="angle">角度</param> /// <returns>旋转后的图像</returns> public static Image Rotate(this Image image, float angle) { using (Mat dst = new Bitmap(image).ToMat()) { Point2f center = new Point2f(dst.Cols / 2, dst.Rows / 2); using (Mat rot = Cv2.GetRotationMatrix2D(center, -angle, 1)) { Size2f s2f = new Size2f(dst.Size().Width, dst.Size().Height); Rect box = new RotatedRect(new Point2f(0, 0), s2f, -angle).BoundingRect(); double xx = rot.At <double>(0, 2) + box.Width / 2 - dst.Cols / 2, zz = rot.At <double>(1, 2) + box.Height / 2 - dst.Rows / 2; rot.Set(0, 2, xx); rot.Set(1, 2, zz); Cv2.WarpAffine(dst, dst, rot, box.Size); GC.SuppressFinalize(s2f); GC.SuppressFinalize(box); GC.SuppressFinalize(xx); GC.SuppressFinalize(zz); GC.Collect(); GC.WaitForPendingFinalizers(); return(dst.ToBitmap()); } } }
public static extern ExceptionStatus core_FileStorage_shift_Size2f(IntPtr fs, Size2f val);
/// <summary> /// /// </summary> /// <param name="box"></param> public RotatedRect(CvBox2D box) { Center = box.Center; Size = box.Size; Angle = box.Angle; }
/// <summary> /// /// </summary> /// <param name="center"></param> /// <param name="size"></param> /// <param name="angle"></param> public RotatedRect(Point2f center, Size2f size, float angle) { Center = center; Size = size; Angle = angle; }
public static extern ExceptionStatus core_Mat_push_back_Size2f(IntPtr self, Size2f v);
public void DewIt() // demo function { Texture2D tex = new Texture2D(1080, 2168, TextureFormat.RGBA32, false); Color fillColor = new Color(0, 0, 0, 0); Color [] fillColorArray = tex.GetPixels(); for (var i = 0; i < fillColorArray.Length; ++i) { fillColorArray[i] = fillColor; } tex.SetPixels(fillColorArray); List <Vector2Int> points = new List <Vector2Int>(); points.Add(new Vector2Int(158, 1101)); points.Add(new Vector2Int(158, 1108)); points.Add(new Vector2Int(165, 1198)); points.Add(new Vector2Int(178, 1281)); points.Add(new Vector2Int(199, 1363)); points.Add(new Vector2Int(239, 1434)); points.Add(new Vector2Int(297, 1490)); points.Add(new Vector2Int(365, 1531)); points.Add(new Vector2Int(442, 1569)); points.Add(new Vector2Int(529, 1528)); points.Add(new Vector2Int(613, 1572)); points.Add(new Vector2Int(682, 1537)); points.Add(new Vector2Int(744, 1493)); points.Add(new Vector2Int(793, 1436)); points.Add(new Vector2Int(818, 1366)); points.Add(new Vector2Int(830, 1289)); points.Add(new Vector2Int(839, 1209)); points.Add(new Vector2Int(842, 1124)); points.Add(new Vector2Int(841, 1089)); points.Add(new Vector2Int(158, 1101)); float time = Time.realtimeSinceStartup; DrawPolygon(tex, points, includeColor); Debug.Log("Execution time of DrawPolygon 1 is " + (Time.realtimeSinceStartup - time)); Vector2 center = new Vector2(499, 1094); Size2f axes = new Size2f(341, 375); time = Time.realtimeSinceStartup; EllipseEx(tex, center, axes, 0, 180, 360, includeColor); Debug.Log("Execution time of EllipseEx 1 is " + (Time.realtimeSinceStartup - time)); Vector2 center2 = new Vector2(390, 1096); Size2f axes2 = new Size2f(73, 32); time = Time.realtimeSinceStartup; EllipseEx(tex, center2, axes2, 0, 0, 360, excludeColor); Debug.Log("Execution time of EllipseEx 2 is " + (Time.realtimeSinceStartup - time)); Vector2 center3 = new Vector2(688, 1091); Size2f axes3 = new Size2f(69, 33); time = Time.realtimeSinceStartup; EllipseEx(tex, center3, axes3, 0, 0, 360, excludeColor); Debug.Log("Execution time of EllipseEx 3 is " + (Time.realtimeSinceStartup - time)); points.Clear(); points.Add(new Vector2Int(247, 1044)); points.Add(new Vector2Int(295, 996)); points.Add(new Vector2Int(363, 979)); points.Add(new Vector2Int(433, 989)); points.Add(new Vector2Int(497, 1018)); points.Add(new Vector2Int(498, 1052)); points.Add(new Vector2Int(434, 1021)); points.Add(new Vector2Int(363, 1008)); points.Add(new Vector2Int(295, 1022)); points.Add(new Vector2Int(247, 1067)); points.Add(new Vector2Int(247, 1044)); time = Time.realtimeSinceStartup; DrawPolygon(tex, points, excludeColor); Debug.Log("Execution time of DrawPolygon 2 is " + (Time.realtimeSinceStartup - time)); points.Clear(); points.Add(new Vector2Int(585, 1011)); points.Add(new Vector2Int(641, 986)); points.Add(new Vector2Int(701, 977)); points.Add(new Vector2Int(762, 987)); points.Add(new Vector2Int(804, 1028)); points.Add(new Vector2Int(804, 1051)); points.Add(new Vector2Int(762, 1010)); points.Add(new Vector2Int(701, 1000)); points.Add(new Vector2Int(641, 1009)); points.Add(new Vector2Int(585, 1034)); points.Add(new Vector2Int(585, 1011)); time = Time.realtimeSinceStartup; DrawPolygon(tex, points, excludeColor); Debug.Log("Execution time of DrawPolygon 3 is " + (Time.realtimeSinceStartup - time)); tex.Apply(); GetComponent <RawImage>().texture = tex; }
public Ellipse(Point2f center, Size2f axes, float angle) { Center = center; Axes = axes; Angle = angle; }
public static extern ExceptionStatus core_FileNode_read_Size2f(IntPtr node, out Size2f returnValue);
static OpenCvSharp.Size ToSize(Size2f size) { return(new OpenCvSharp.Size(size.Width, size.Height)); }
public static extern void core_Mat_push_back_Size2f(IntPtr self, Size2f v);
public GtEllipse(Point2f center, Size2f axes, float angle, Size imageSize) : base(center, axes, angle) { ImageSize = imageSize; }
static List <Vector2> ellipse2Poly(Vector2 center, Size2f axes, int angle, int arc_start, int arc_end, int delta) { List <Vector2> points = new List <Vector2>(); float alpha, beta; int i; while (angle < 0) { angle += 360; } while (angle > 360) { angle -= 360; } if (arc_start > arc_end) { i = arc_start; arc_start = arc_end; arc_end = i; } while (arc_start < 0) { arc_start += 360; arc_end += 360; } while (arc_end > 360) { arc_end -= 360; arc_start -= 360; } if (arc_end - arc_start > 360) { arc_start = 0; arc_end = 360; } sincos(angle, out alpha, out beta); points.Clear(); for (i = arc_start; i < arc_end + delta; i += delta) { float x, y; angle = i; if (angle > arc_end) { angle = arc_end; } if (angle < 0) { angle += 360; } x = axes.width * SinTable[450 - angle]; y = axes.height * SinTable[angle]; Vector2 pt; pt.x = center.x + x * alpha - y * beta; pt.y = center.y + x * beta + y * alpha; points.Add(pt); } return(points); }
public ExtractRectangleAction() { Name = "Extract rectangle"; Action = (input) => { input.FindContours(out var contours, out var hierarchy, RetrievalModes.List, ContourApproximationModes.ApproxNone); var m = input.CvtColor(ColorConversionCodes.GRAY2BGR); var imageArea = m.Width * m.Height; var allContoursSelect = from contour in contours let boundingRect = Cv2.MinAreaRect(contour) let boundingRectArea = boundingRect.Size.Width * boundingRect.Size.Height let convexHull = Cv2.ConvexHull(contour) let hullArea = Cv2.ContourArea(convexHull) let contourPercentage = hullArea / boundingRectArea let wtoh = boundingRect.Size.Width / boundingRect.Size.Height let htow = boundingRect.Size.Height / boundingRect.Size.Width select new { boundingRect.Center, Wtoh = wtoh, Htow = htow, ImageArea = hullArea / imageArea, BoundingRect = boundingRect, Pixels = boundingRect.Size.Width * boundingRect.Size.Height, ContourPerc = contourPercentage, ConvexHull = convexHull, HullArea = hullArea, RectArea = boundingRect.Size.Width * boundingRect.Size.Height }; if (this.EnableFilters) { allContoursSelect = allContoursSelect .Where(i => i.Pixels >= this.MinRectPixels && i.Pixels <= this.MaxRectPixels && i.ContourPerc >= this.MinRectShapeArea && (Math.Abs(i.Wtoh - this.WidthToHeightRatio) <= this.WidthToHeightRatioDeviation || Math.Abs(i.Htow - this.WidthToHeightRatio) <= this.WidthToHeightRatioDeviation)); switch (this.SelectionMode) { case RectangleSelectionMode.MostNorth: allContoursSelect = allContoursSelect.OrderByDescending(c => c.Center.Y); break; case RectangleSelectionMode.MostSouth: allContoursSelect = allContoursSelect.OrderBy(c => c.Center.Y); break; case RectangleSelectionMode.MostEast: allContoursSelect = allContoursSelect.OrderByDescending(c => c.Center.Y); break; case RectangleSelectionMode.MostWest: allContoursSelect = allContoursSelect.OrderBy(c => c.Center.Y); break; case RectangleSelectionMode.BiggestBoundingRectArea: allContoursSelect = allContoursSelect.OrderBy(c => c.RectArea); break; case RectangleSelectionMode.SmallestBoundingRectArea: allContoursSelect = allContoursSelect.OrderByDescending(c => c.RectArea); break; case RectangleSelectionMode.BiggestConvexHullArea: allContoursSelect = allContoursSelect.OrderBy(c => c.HullArea); break; case RectangleSelectionMode.SmallestConvexHullArea: allContoursSelect = allContoursSelect.OrderByDescending(c => c.HullArea); break; default: throw new Exception($"Missing mode handling: {this.SelectionMode}"); } } var allContours = allContoursSelect .ToArray(); this.Status = $"{allContours.Length} found ({contours.Length} unfiltered)"; this.DetectedRect = string.Empty; if (allContours.Length == 0) { throw new Exception("No contours found that match the criteria."); } var contourOfInterest = allContours.Last(); this.DetectedRect = $"ImageArea: {contourOfInterest.ImageArea}\n" + $"Pixels: {contourOfInterest.Pixels:F0}\n" + $"RectShapeArea: {contourOfInterest.ContourPerc:P2}\n" + $"WidthToHeight: {contourOfInterest.Wtoh}\n" + $"HeightToWidth: {contourOfInterest.Htow}"; if (!this.Crop) { // Draw contours. foreach (var contour in allContours) { var color = contour == contourOfInterest ? Scalar.Green : Scalar.Red; m.Polylines(new[] { contour.BoundingRect.Points().Select(p => new Point(p.X, p.Y)) }, isClosed: true, color); m.DrawContours(new[] { contour.ConvexHull }, 0, color); } input.Dispose(); return(m); } // Crop! var angle = contourOfInterest.BoundingRect.Angle; var size = contourOfInterest.BoundingRect.Size; if (angle < -45) { angle += 90.0f; size = new Size2f(size.Height, size.Width); } var rotMatrix = Cv2.GetRotationMatrix2D(contourOfInterest.BoundingRect.Center, angle, 1.0); var warped = m.WarpAffine(rotMatrix, m.Size(), InterpolationFlags.Cubic); input.Dispose(); m.Dispose(); return(warped.GetRectSubPix(new Size(size.Width, size.Height), contourOfInterest.BoundingRect.Center)); }; }