2026-01-26 18:56:53 +09:00

280 lines
12 KiB
C#

/*
* Copyright (c) 2025 LG Electronics Inc.
* SPDX-License-Identifier: LicenseRef-LGE-Proprietary
*/
using Aurora.Api;
using VisionLight;
using VisionCommon;
using System;
using System.Collections.Generic;
using VisionCalibrator;
using Aurora.Api.DataType;
using VisionSequence.Camera;
using System.Threading;
namespace VisionSequence.Pattern {
/// <summary>
/// 공정 중 취득한 이미지와 패턴 정보를 관리하기 위함.
/// </summary>
public class GrabFindSeqUtil {
private static Logger _Logger = new Logger("GrabFindSeqUtil");
private static readonly object _Lock = new object();
/// <summary>
/// 공정 조명 값이 동일할 때, 그랩을 스킵하고 재활용할 이미지 저장
/// </summary>
private static Dictionary<FovInfo, ProcGrabImageManager> _ProcGrabImageManagers
= new Dictionary<FovInfo, ProcGrabImageManager>();
/// <summary>
/// 공정 Fixture 패턴 저장
/// </summary>
private static Dictionary<FovInfo, PatternResult> _FixturePatternResults
= new Dictionary<FovInfo, PatternResult>();
#region Grab Image (조명 값이 동일할 경우 그랩을 스킵하는 용도)
/// <summary>
/// 등록 패턴의 조명 값이 마지막 조명 값과 동일한지 체크 (그랩 생략을 위함)
/// </summary>
public static bool IsPatternAndLastLightSame(FovInfo fovInfo, PatternInfo patternInfo) {
try {
foreach (LightParam lightParam in patternInfo.LightInfo.LightParams) {
int ch = lightParam.Ch;
int lastLevel = LightHub.Instance.GetLightConfigInfo(lightParam.LightId, lightParam.Ch).ChConfig.Level;
int patternLevel = lightParam.Level;
bool patternOnOff = lightParam.OnOff;
// 패턴 조명 값이 마지막 조명 값과 다른 경우
if (patternLevel != lastLevel) {
if (!patternOnOff && lastLevel == 0) {
continue; // 조명 값은 다르지만, 그랩을 새로 안해도 되는 경우
}
else {
return false; // 조명 값이 달라서 그랩을 새로 해야하는 경우
}
}
// 패턴 조명 값이 마지막 조명 값과 같은 경우
else {
if (!patternOnOff && lastLevel != 0) {
return false; // 조명 값은 같지만, 그랩을 새로 해야하는 경우
}
else {
continue; // 조명 값이 같아서 그랩을 새로 안해도 되는 경우
}
}
}
}
catch (Exception e) {
_Logger.FuncE(e.Message);
}
return true; // 조명 값이 같아서 그랩을 새로 안해도 됨
}
/// <summary>
/// 그랩 완료 여부를 체크한다.
/// </summary>
/// <param name="fovInfo">FOV 키 정보</param>
/// <param name="lightInfo">조명 값</param>
/// <returns>그랩 완료 여부</returns>
public static bool IsProcGrabDone(FovInfo fovInfo, LightInfo lightInfo) {
var procGrabImageManager = GetProcGrabImageManager(fovInfo);
return procGrabImageManager.IsGrabDone(lightInfo);
}
/// <summary>
/// 그랩 완료된 공정 이미지를 등록한다.
/// </summary>
/// <param name="fovInfo">FOV 키 정보</param>
/// <param name="lightInfo">조명 값</param>
/// <param name="image">공정 그랩 이미지</param>
public static void SetProcGrabImage(FovInfo fovInfo, LightInfo lightInfo, object image) {
var procGrabImageManager = GetProcGrabImageManager(fovInfo);
procGrabImageManager.SetGrabImage(lightInfo, image);
}
/// <summary>
/// 그랩 완료된 공정 이미지를 얻어온다.
/// </summary>
/// <param name="fovInfo">FOV 키 정보</param>
/// <param name="lightInfo">조명 값</param>
/// <returns>공정 이미지</returns>
public static object GetProcGrabImage(FovInfo fovInfo, LightInfo lightInfo) {
var procGrabImageManager = GetProcGrabImageManager(fovInfo);
return procGrabImageManager.GetGrabImage(lightInfo);
}
private static ProcGrabImageManager GetProcGrabImageManager(FovInfo fovInfo) {
lock (_Lock) {
if (!_ProcGrabImageManagers.ContainsKey(fovInfo)) {
_ProcGrabImageManagers[fovInfo] = new ProcGrabImageManager(
fovInfo, CameraAgentManager.GetCameraAgent(fovInfo));
}
return _ProcGrabImageManagers[fovInfo];
}
}
/// <summary>
/// 공정 이미지들을 정리한다.
/// </summary>
/// <param name="fovInfo">FOV 키 정보</param>
public static void ClearProcGrabImage(FovInfo fovInfo) {
var procGrabImageManager = GetProcGrabImageManager(fovInfo);
procGrabImageManager.Clear();
}
#endregion
#region Fixture Pattern
/// <summary>
/// Fixture 패턴의 검출 결과를 등록한다.
/// </summary>
/// <param name="fovInfo">FOV 키 정보</param>
/// <param name="patternResult">패턴 검출 결과</param>
public static void SetFixturePatternResult(FovInfo fovInfo, PatternResult patternResult) {
if (!_FixturePatternResults.ContainsKey(fovInfo)) {
lock (_Lock) {
_FixturePatternResults.Add(fovInfo, patternResult);
}
}
else {
lock (_Lock) {
_FixturePatternResults[fovInfo] = patternResult;
}
}
}
/// <summary>
/// Fixture 패턴의 검출 결과를 얻어온다.
/// </summary>
/// <param name="fovInfo">FOV 키 정보</param>
/// <returns>Fixture 패턴의 검출 결과</returns>
public static PatternResult GetFixturePatternResult(FovInfo fovInfo) {
if (_FixturePatternResults.ContainsKey(fovInfo)) {
return _FixturePatternResults[fovInfo];
}
else {
_Logger.FuncE("FixturePatternResult is null.");
return null;
}
}
/// <summary>
/// Fixture 패턴의 검출 결과를 정리한다.
/// <param name="fovInfo">FOV 키 정보</param>
/// </summary>
public static void ClearFixturePatternResult(FovInfo fovInfo) {
if (_FixturePatternResults.ContainsKey(fovInfo)) {
_FixturePatternResults.Remove(fovInfo);
}
}
#endregion
#region Clear Images & Fixture Patterns
/// <summary>
/// 곻정 이미지, 패턴 정보 초기화
/// </summary>
/// <param name="subSysInfo">서브시스템 정보</param>
public static void Clear(SubSysInfo subSysInfo) {
lock (_Lock) {
foreach (var fovInfo in VisionRecipeManager.GetFovInfos(subSysInfo)) {
ClearProcGrabImage(fovInfo);
ClearFixturePatternResult(fovInfo);
}
}
}
/// <summary>
/// 곻정 이미지, 패턴 정보 초기화
/// </summary>
/// <param name="fovInfo">FOV 키 정보</param>
public static void Clear(FovInfo fovInfo) {
lock (_Lock) {
ClearProcGrabImage(fovInfo);
ClearFixturePatternResult(fovInfo);
}
}
#endregion
public static List<PatternResult> FindMulti(
FovInfo fovInfo, PatternInfo masterPatternInfo, PatternAgentBase patternAgent,
Calibrator calibrator, CameraAgentBase cameraAgent, ICameraDisplay cameraDisplay,
object grabImage, FixtureResult fixtureResult = null) {
var patternResults = patternAgent.FindMulti(masterPatternInfo, grabImage, cameraDisplay, fixtureResult);
for (int i = 1; i < patternResults.Count; i++) {
PatternResult slavePatternResult = patternResults[i];
TransformCoord(calibrator, cameraAgent.GetImageSize(), ref slavePatternResult);
var slavePatternInfo = patternAgent.GetPatternInfo(slavePatternResult.PatternIndex);
patternAgent.Draw(slavePatternInfo, slavePatternResult, cameraDisplay, isFixturePattern: false);
slavePatternResult.PatternName = slavePatternInfo.PatternName;
slavePatternResult.PatternType = slavePatternInfo.PatternType;
slavePatternResult.FovId = fovInfo.FovId;
}
return patternResults;
}
/// <summary>
/// 패턴 검출 결과의 이미지 좌표를 자재 좌표로 변환한다.
/// </summary>
/// <param name="calibrator">캘리브레이터 디바이스</param>
/// <param name="imageSize">이미지 사이즈 정보</param>
/// <param name="patternResult">패턴 검출 결과</param>
public static void TransformCoord(
Calibrator calibrator, ImageSize imageSize, ref PatternResult patternResult) {
try {
lock (_Lock) {
if (patternResult.Results == null) {
_Logger.FuncE("patternResult.Results is null.");
return;
}
foreach (BaseResult baseResult in patternResult.Results) {
if(!(baseResult.ImagePosition is null)) {
var calibratedPoint = calibrator.TransformToCalibratedSpace(baseResult.ImagePosition, imageSize);
baseResult.MaterialPosition.X = calibratedPoint.X;
baseResult.MaterialPosition.Y = calibratedPoint.Y;
if (baseResult is CaliperResult) {
var caliperResult = baseResult as CaliperResult;
calibratedPoint = calibrator.TransformToCalibratedSpace(caliperResult.ImagePositionSecond, imageSize);
caliperResult.MaterialPositionSecond.X = calibratedPoint.X;
caliperResult.MaterialPositionSecond.Y = calibratedPoint.Y;
calibratedPoint = calibrator.TransformToCalibratedSpace(caliperResult.ImagePositionSecond_VI, imageSize);
caliperResult.MaterialPositionSecond_VI.X = calibratedPoint.X;
caliperResult.MaterialPositionSecond_VI.Y = calibratedPoint.Y;
caliperResult.SetWidthMm(patternResult.PatternType);
}
}
}
_Logger.I(patternResult.ToString());
}
}
catch (Exception e) {
_Logger.FuncE(e.Message);
}
}
/// <summary>
/// 강제 OK 이벤트 발생시키고 강제 OK 결과를 가져온다.
/// </summary>
/// <param name="forceOkReqParam">강제 OK 요청 파라미터</param>
/// <returns>강제 OK 패턴 검출 결과</returns>
public static PatternResult DoForceOk(ForceOkReqParam forceOkReqParam) {
VisionEnv.AuroraEnv.EventPublisher.Publish(new EventMessage(
forceOkReqParam.FovInfo.GetKey(), VisionEventId.REQUEST_PATTERN_FORCE_OK, forceOkReqParam));
while (!forceOkReqParam.IsDone) {
Thread.Sleep(100);
}
return forceOkReqParam.PatternResult;
}
}
}