2026-01-26 14:51:28 +09:00

392 lines
17 KiB
C#

/*
* 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 {
/// <summary>
/// LineFinderRunParam 클래스
/// </summary>
public class LineFinderRunParam : IRunParam, ICloneable {
public ePolarity Polarity { get; set; } = ePolarity.Any;
/// <summary>
/// 찾을 캘리퍼 개수
/// </summary>
public int SubRegionNumber { get; set; } = 8;
/// <summary>
/// 무시할 캘리퍼 개수 (점수가 낮은 캘리퍼는 무시하는 것이 라인 피팅에 유리함)
/// </summary>
public int SubRegionNumberToIgnore { get; set; } = 0;
/// <summary>
/// SubRegionNumberToIgnoreEnabled
/// </summary>
public bool SubRegionNumberToIgnoreEnabled { get; set; } = true;
/// <summary>
/// FindROI
/// </summary>
public ROI FindROI { get; set; } = new ROI();
/// <summary>
/// Clone
/// </summary>
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<CogFindLineTool, double, PatternResult> 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<CogFindLineTool, double, PatternResult> 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<Cross>();
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<Cross>();
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<LineFinderResult>();
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<LineFinderResult>()
};
}
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<string>();
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<string>();
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);
}
}
}
}