using Hawkeye.VisionBuilder.Workflow.Datatypes.Elements.Origin; using Hawkeye.VisionBuilder.Workflow.Datatypes.Elements.Rectangle; using Hawkeye.VisionBuilder.Workflow.Operations.Attributes; using OpenCvSharp; using System; using System.Security.Cryptography.Xml; using Point = OpenCvSharp.Point; namespace Hawkeye.VisionBuilder.Workflow.Operations; [Category("Simple/Blobs")] public class FindRectangleOperation:BaseOperation { private readonly WorkflowList _workflowList; public int MinWidth { get; set; } public int MaxWidth { get; set; } = 999999; public int MinHeight { get; set; } public int MaxHeight { get; set; } = 999999; public Guid ReferenceId { get; set; } = new Guid(); public bool BadIfFound { get; set; }=false; public FindRectangleOperation(WorkflowList workflowList) { _workflowList = workflowList; SearchArea = new RectangleElement() { Editable = true, Location = Vector2.One * 100, Size = Vector2.One * 100, IsGood = true }; } public RectangleElement SearchArea { get; set; } //processing result of current element [NotForTool] public OriginElement Origin { get; private set; } = OriginElement.Default; protected override void InterpretInternal(Context context) { if(!CheckImageExists(context)) return; SearchArea.MovePivot(_workflowList.GetOriginById(ReferenceId).Origin.Location); var image = context.ActiveImage.ImageData; var mat = new Mat(image.Size(), image.Type(), Scalar.Black); SearchArea.FillMat(mat); var contoursMat = image.BitwiseAnd(mat).ToMat(); context.GraphicsElements.Add(SearchArea); // find rectangle on image Cv2.FindContours(contoursMat, out var contours, out _, RetrievalModes.External, ContourApproximationModes.ApproxSimple); foreach (Point[] contour in contours) { var rect = Cv2.BoundingRect(contour); if (rect.Width >= MinWidth && rect.Width <= MaxWidth && rect.Height >= MinHeight && rect.Height <= MaxHeight) { Status = "Rectangle: " + rect; Result = !BadIfFound; RectangleElement re = new RectangleElement() { Editable = false, IsGood = !BadIfFound, Location = new Vector2(rect.X, rect.Y), Size = new Vector2(rect.Width, rect.Height) }; context.GraphicsElements.Add(re); return; } } Status = "No rectangle found"; Result = BadIfFound; } public override void SetParameters(Dictionary parameters) { base.SetParameters(parameters); SearchArea.SetPivot(_workflowList.GetOriginById(ReferenceId).Origin.Location); } public override void Save(BinaryWriter bw) { base.Save(bw); bw.Write(ReferenceId.ToString()); bw.Write(MinWidth); bw.Write(MaxWidth); bw.Write(MinHeight); bw.Write(MaxHeight); bw.Write(BadIfFound); SearchArea.Save(bw); } public override void Load(BinaryReader br) { base.Load(br); ReferenceId = new Guid(br.ReadString()); MinWidth = br.ReadInt32(); MaxWidth = br.ReadInt32(); MinHeight = br.ReadInt32(); MaxHeight = br.ReadInt32(); BadIfFound = br.ReadBoolean(); SearchArea.Load(br); } public override void Save(Dictionary dict) { base.Save(dict); dict[nameof(MinWidth)] = MinWidth; dict[nameof(MaxWidth)] = MaxWidth; dict[nameof(MinHeight)] = MinHeight; dict[nameof(MaxHeight)] = MaxHeight; dict[nameof(BadIfFound)] = BadIfFound; dict[nameof(ReferenceId)] = ReferenceId.ToString(); // Save SearchArea properties manually dict["SearchArea_Editable"] = SearchArea.Editable; dict["SearchArea_IsGood"] = SearchArea.IsGood; dict["SearchArea_LocationX"] = SearchArea.Location.X; dict["SearchArea_LocationY"] = SearchArea.Location.Y; dict["SearchArea_OffsetX"] = SearchArea.Offset.X; dict["SearchArea_OffsetY"] = SearchArea.Offset.Y; dict["SearchArea_SizeX"] = SearchArea.Size.X; dict["SearchArea_SizeY"] = SearchArea.Size.Y; } public override void Load(Dictionary dict) { base.Load(dict); if (dict.ContainsKey(nameof(MinWidth))) MinWidth = Convert.ToInt32(dict[nameof(MinWidth)]); if (dict.ContainsKey(nameof(MaxWidth))) MaxWidth = Convert.ToInt32(dict[nameof(MaxWidth)]); if (dict.ContainsKey(nameof(MinHeight))) MinHeight = Convert.ToInt32(dict[nameof(MinHeight)]); if (dict.ContainsKey(nameof(MaxHeight))) MaxHeight = Convert.ToInt32(dict[nameof(MaxHeight)]); if (dict.ContainsKey(nameof(BadIfFound))) BadIfFound = Convert.ToBoolean(dict[nameof(BadIfFound)]); if (dict.ContainsKey(nameof(ReferenceId))) ReferenceId = new Guid(dict[nameof(ReferenceId)].ToString()); // Load SearchArea properties manually if (dict.ContainsKey("SearchArea_Editable")) SearchArea.Editable = Convert.ToBoolean(dict["SearchArea_Editable"]); if (dict.ContainsKey("SearchArea_IsGood")) SearchArea.IsGood = Convert.ToBoolean(dict["SearchArea_IsGood"]); if (dict.ContainsKey("SearchArea_LocationX") && dict.ContainsKey("SearchArea_LocationY")) SearchArea.Location = new Vector2(Convert.ToSingle(dict["SearchArea_LocationX"]), Convert.ToSingle(dict["SearchArea_LocationY"])); if (dict.ContainsKey("SearchArea_OffsetX") && dict.ContainsKey("SearchArea_OffsetY")) SearchArea.Offset = new Vector2(Convert.ToSingle(dict["SearchArea_OffsetX"]), Convert.ToSingle(dict["SearchArea_OffsetY"])); if (dict.ContainsKey("SearchArea_SizeX") && dict.ContainsKey("SearchArea_SizeY")) SearchArea.Size = new Vector2(Convert.ToSingle(dict["SearchArea_SizeX"]), Convert.ToSingle(dict["SearchArea_SizeY"])); } }