392 lines
17 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|
|
}
|