/* * Copyright (c) 2025 LG Electronics Inc. * SPDX-License-Identifier: LicenseRef-LGE-Proprietary */ using Aurora.Api; using CogCommon; using VisionCommon; using Hermes; using Cognex.VisionPro; using Cognex.VisionPro.Caliper; using System; using System.Collections.Generic; using Aurora.Api.DataType; using System.Linq; using System.Diagnostics; using System.Runtime.Serialization.Formatters.Binary; namespace CogPattern { /// /// LineFinderRunParam 클래스 /// public class LineFinderRunParam : IRunParam, ICloneable { public ePolarity Polarity { get; set; } = ePolarity.Any; /// /// 찾을 캘리퍼 개수 /// public int SubRegionNumber { get; set; } = 8; /// /// 무시할 캘리퍼 개수 (점수가 낮은 캘리퍼는 무시하는 것이 라인 피팅에 유리함) /// public int SubRegionNumberToIgnore { get; set; } = 0; /// /// SubRegionNumberToIgnoreEnabled /// public bool SubRegionNumberToIgnoreEnabled { get; set; } = true; /// /// FindROI /// public ROI FindROI { get; set; } = new ROI(); /// /// Clone /// public object Clone() { return new LineFinderRunParam() { Polarity = this.Polarity, SubRegionNumber = this.SubRegionNumber, SubRegionNumberToIgnore = this.SubRegionNumberToIgnore, SubRegionNumberToIgnoreEnabled = this.SubRegionNumberToIgnoreEnabled, FindROI = this.FindROI.Clone() as ROI }; } } class Line { public ImagePoint Start { get; set; } public ImagePoint End { get; set; } public double Length { get; private set; } public Line(ImagePoint start, ImagePoint end) { Start = start; End = end; Length = MathUtil.CalculateDistance(Start, End); } } internal static class CogMeasureLine { private static readonly Logger _Logger = new Logger(typeof(CogMeasureLine).Name); public static CogFindLineTool CreateTool() { CogFindLineTool cogFindLineTool = new CogFindLineTool(); return cogFindLineTool; } public static CogFindLineTool LoadTool(string filePath) { return (CogFindLineTool)CogSerializer.LoadObjectFromFile( filePath, typeof(BinaryFormatter), CogSerializationOptionsConstants.Minimum); } public static int SaveTool(CogFindLineTool cogFindLineTool, string filePath) { if (cogFindLineTool != null && filePath != null) { CogSerializer.SaveObjectToFile( cogFindLineTool, filePath, typeof(BinaryFormatter), CogSerializationOptionsConstants.Minimum); return E1.OK; } return E1.GENERIC; } public static void FreeTool(CogFindLineTool cogFindLineTool) { if (cogFindLineTool != null) { cogFindLineTool = null; } } public static ROI GetFindROI(CogFindLineTool cogFindLineTool) { double left = cogFindLineTool.RunParams.ExpectedLineSegment.StartX; double top = cogFindLineTool.RunParams.ExpectedLineSegment.StartY; double right = cogFindLineTool.RunParams.ExpectedLineSegment.EndX; double bottom = cogFindLineTool.RunParams.ExpectedLineSegment.EndY; double boxCenterX = (left + right) / 2; double boxCenterY = (top + bottom) / 2; double width = cogFindLineTool.RunParams.ExpectedLineSegment.Length; double height = cogFindLineTool.RunParams.CaliperSearchLength; double angleDeg = CogMisc.RadToDeg(cogFindLineTool.RunParams.ExpectedLineSegment.Rotation); return new ROI( new ImagePoint(boxCenterX, boxCenterY), (int)width, (int)height, Angle.CreateWithDegree(angleDeg)); } public static int SetFindROI(CogFindLineTool cogFindLineTool, ROI findRoi) { cogFindLineTool.RunParams.CaliperProjectionLength = (int)findRoi.Width / cogFindLineTool.RunParams.NumCalipers; // 서브 영역 너비 cogFindLineTool.RunParams.CaliperSearchLength = findRoi.Height; // 서브 영역 높이 cogFindLineTool.RunParams.ExpectedLineSegment.SetStartLengthRotation(findRoi.RotatedLeftCenter.X, findRoi.RotatedLeftCenter.Y, findRoi.Width, findRoi.Angle.Radian); return E1.OK; } public static PatternResult Find( CogFindLineTool cogFindLineTool, ICogImage image, Func funcExtractResults, ROI findRoi) { var patternResult = new PatternResult(); var oldFindRoi = GetFindROI(cogFindLineTool); try { SetFindROI(cogFindLineTool, findRoi); patternResult = Find(cogFindLineTool, image, funcExtractResults); } catch (Exception e) { _Logger.FuncE(e.Message); } finally { SetFindROI(cogFindLineTool, oldFindRoi); } return patternResult; } public static PatternResult Find( CogFindLineTool cogFindLineTool, ICogImage image, Func funcExtractResults) { var timeFind = new Stopwatch(); timeFind.Start(); cogFindLineTool.InputImage = (CogImage8Grey)image; cogFindLineTool.Run(); timeFind.Stop(); double tactTime = timeFind.ElapsedMilliseconds; return funcExtractResults(cogFindLineTool, tactTime); } public static void DrawSubPositions(CogFindLineTool cogFindLineTool, ICogCameraDisplay cogCameraDisplay) { if (CogMeasureCommon.IsLineFound(cogFindLineTool)) { var crosses = new List(); int crossLength = 15; foreach (CogFindLineResult findResult in cogFindLineTool.Results) { if (findResult.CaliperResults?.Count > 0) { foreach (CogCaliperResult caliperResult in findResult.CaliperResults) { CogCaliperEdge edge0 = caliperResult.Edge0; if (edge0.PositionX != 0 || edge0.PositionY != 0) { var point = new ImagePoint(caliperResult.Edge0.PositionX, caliperResult.Edge0.PositionY); crosses.Add(new Cross(point, crossLength)); } } } } cogCameraDisplay.AddCrosses(crosses, GraphicColors.PatternAdditionInfo); } } public static void DrawPosition(CogFindLineTool cogFindLineTool, ICogCameraDisplay cogCameraDisplay) { if (CogMeasureCommon.IsLineFound(cogFindLineTool)) { int numOfResult = cogFindLineTool.Results[0].CaliperResults.Count; var crosses = new List(); if (0 < numOfResult) { ImagePoint posCenter = GetCenterPosOfLine(cogFindLineTool); var color = GraphicColors.PatternFoundOK; var cross = new Cross(posCenter.Clone() as ImagePoint, 5); crosses.Add(cross); cogCameraDisplay.SetPatternTracking(cross); cogCameraDisplay.AddCross(cross, color); cogCameraDisplay.DrawPatternTrackings(crosses); } } } public static ImagePoint GetCenterPosOfLine(CogFindLineTool cogFindLineTool) { CogLineSegment cogLineSegment = cogFindLineTool.Results.GetLineSegment(); // 라인 ROI의 중심이 아닌 검출된 라인의 중심임에 주의 return new ImagePoint() { X = (cogLineSegment.StartX + cogLineSegment.EndX) / 2, Y = (cogLineSegment.StartY + cogLineSegment.EndY) / 2 }; } public static IRunParam GetRunParam(CogFindLineTool cogFindLineTool) { return new LineFinderRunParam() { SubRegionNumber = cogFindLineTool.RunParams.NumCalipers, SubRegionNumberToIgnore = cogFindLineTool.RunParams.NumToIgnore, SubRegionNumberToIgnoreEnabled = cogFindLineTool.RunParams.DecrementNumToIgnore, Polarity = CogMeasureCommon.ConvertToPolarity(cogFindLineTool.RunParams.CaliperRunParams.Edge0Polarity), FindROI = GetFindROI(cogFindLineTool) }; } public static int SetRunParam(CogFindLineTool cogFindLineTool, IRunParam runParam) { if (runParam is LineFinderRunParam) { var param = runParam as LineFinderRunParam; cogFindLineTool.RunParams.NumCalipers = param.SubRegionNumber; cogFindLineTool.RunParams.NumToIgnore = param.SubRegionNumberToIgnore; cogFindLineTool.RunParams.DecrementNumToIgnore = param.SubRegionNumberToIgnoreEnabled; cogFindLineTool.RunParams.CaliperRunParams.EdgeMode = CogCaliperEdgeModeConstants.SingleEdge; cogFindLineTool.RunParams.CaliperRunParams.Edge0Polarity = CogMeasureCommon.ConvertToCogCaliperPolarity(param.Polarity); SetFindROI(cogFindLineTool, param.FindROI); return E1.OK; } return E1.GENERIC; } public static PatternResult Find(CogFindLineTool cogFindLineTool, ICogImage image, IRunParam runParam) { SetRunParam(cogFindLineTool, runParam); return Find(cogFindLineTool, image); } public static PatternResult Find(CogFindLineTool cogFindLineTool, ICogImage image, ROI findRoi) { return Find(cogFindLineTool, image, ExtractResults, findRoi); } public static PatternResult Find(CogFindLineTool cogFindLineTool, ICogImage image) { return Find(cogFindLineTool, image, ExtractResults); } private static PatternResult ExtractResults(CogFindLineTool cogFindLineTool, double tactTime) { var results = new List(); if (CogMeasureCommon.IsLineFound(cogFindLineTool)) { ImagePoint posCenter = GetCenterPosOfLine(cogFindLineTool); double angle = CogMisc.RadToDeg(cogFindLineTool.Results.GetLine().Rotation); results.Add(new LineFinderResult( posCenter, Angle.CreateWithDegree(angle), GetLineEquation(cogFindLineTool), cogFindLineTool)); } return new PatternResult() { PatternType = ePatternType.LineFinder, Status = (results.Count > 0) ? eFoundStatus.FoundOK : eFoundStatus.NotFound, Results = results, FindRoi = GetFindROI(cogFindLineTool), TactTimeInMilliSec = tactTime }; } private static LineEquation GetLineEquation(CogFindLineTool cogFindLineTool) { double startX = 0, startY = 0, endX = 0, endY = 0; cogFindLineTool.Results.GetLineSegment().GetStartEnd(out startX, out startY, out endX, out endY); return new LineEquation(startX, startY, endX, endY); } public static PatternResult GetNotFoundPatternResult() { return new PatternResult() { Status = eFoundStatus.NotFound, Results = new List() }; } public static void Draw(CogFindLineTool cogFindLineTool, PatternResult patternResult, ICogCameraDisplay cogCameraDisplay) { DrawSubPositions(cogFindLineTool, cogCameraDisplay); DrawLine(cogFindLineTool, cogCameraDisplay); DrawText(patternResult, cogCameraDisplay); DrawPosition(cogFindLineTool, cogCameraDisplay); } [Obsolete] public static void Draw(CogFindLineTool cogFindLineTool, LineFinderResult lineFinderResult, ICogCameraDisplay cogCameraDisplay) { DrawSubPositions(cogFindLineTool, cogCameraDisplay); DrawLine(cogFindLineTool, cogCameraDisplay); DrawText(lineFinderResult, cogCameraDisplay); DrawPosition(cogFindLineTool, cogCameraDisplay); } private static void DrawLine(CogFindLineTool cogFindLineTool, ICogCameraDisplay cogCameraDisplay) { if (CogMeasureCommon.IsLineFound(cogFindLineTool)) { int numOfResult = cogFindLineTool.Results[0].CaliperResults.Count; if (0 < numOfResult) { var imageSize = CogEnvironment.GetImageSize(cogCameraDisplay.GetImage()); var lineEquation = GetLineEquation(cogFindLineTool); var line = CogMeasureCommon.GetMinLengthLine(lineEquation, imageSize); cogCameraDisplay.AddLine( GraphicColors.PatternFoundOK, line.StartPoint, line.EndPoint); } } } private static void DrawText(PatternResult patternResult, ICogCameraDisplay cogCameraDisplay) { if (patternResult.Status == eFoundStatus.FoundOK) { foreach (BaseResult baseResult in patternResult.Results) { var lineFinderResult = baseResult as LineFinderResult; DrawText(patternResult, lineFinderResult, cogCameraDisplay); } } } private static void DrawText(LineFinderResult lineFinderResult, ICogCameraDisplay cogCameraDisplay) { if (lineFinderResult != null) { var msgs = new List(); msgs.Add(string.Format("X : {0:0.00}", lineFinderResult.ImagePosition.X)); msgs.Add(string.Format("Y : {0:0.00}", lineFinderResult.ImagePosition.Y)); msgs.Add(string.Format("Angle : {0:0.00}", lineFinderResult.Angle.Degree)); cogCameraDisplay.AddTextList( GraphicColors.PatternFoundOK, new ImagePoint(lineFinderResult.ImagePosition.X, lineFinderResult.ImagePosition.Y), msgs); } } private static void DrawText(PatternResult patternResult, LineFinderResult lineFinderResult, ICogCameraDisplay cogCameraDisplay) { if (lineFinderResult != null) { var msgs = new List(); msgs.Add(string.Format("X : {0:0.00}", lineFinderResult.ImagePosition.X)); msgs.Add(string.Format("Y : {0:0.00}", lineFinderResult.ImagePosition.Y)); msgs.Add(string.Format("Angle : {0:0.00}", lineFinderResult.Angle.Degree)); msgs.Add(string.Format("TactTime : {0:F3} ms", patternResult.TactTimeInMilliSec)); msgs.Add(string.Format("ID : {0}_{1}", patternResult.PatternIndex?.PatternId, patternResult.PatternIndex?.PatternSubId)); cogCameraDisplay.AddTextList( GraphicColors.PatternFoundOK, new ImagePoint(lineFinderResult.ImagePosition.X, lineFinderResult.ImagePosition.Y), msgs); } } public static void DrawCaliperROI(CogFindLineTool cogFindLineTool, ICogCameraDisplay cogCameraDisplay, ROI findRoi) { var oldFindRoi = GetFindROI(cogFindLineTool); try { SetFindROI(cogFindLineTool, findRoi); //CogLineSegment cogLineSegment = new CogLineSegment(); CogGraphicCollection cogGraphicCollection = new CogGraphicCollection(); cogFindLineTool.CurrentRecordEnable = CogFindLineCurrentRecordConstants.All; ICogRecord cogRecord = cogFindLineTool.CreateCurrentRecord(); //cogLineSegment = cogRecord.SubRecords["InputImage"].SubRecords["ExpectedShapeSegment"].Content as CogLineSegment; cogGraphicCollection = cogRecord.SubRecords["InputImage"].SubRecords["CaliperRegions"].Content as CogGraphicCollection; var cogDisplay = cogCameraDisplay.GetDisplay(); //cogDisplay.InteractiveGraphics.Add(cogLineSegment, CogConstants.KEY_LINE_SEGMENT, false); foreach (ICogGraphic g in cogGraphicCollection) { g.Color = CogColorConstants.Grey; cogDisplay.StaticGraphics.Add(g as ICogGraphicInteractive, CogConstants.KEY_CALIPER_ROI); } } catch (Exception e) { _Logger.FuncE(e.Message); } finally { SetFindROI(cogFindLineTool, oldFindRoi); } } } }