319 lines
14 KiB
C#
319 lines
14 KiB
C#
/*
|
|
* Copyright (c) 2025 LG Electronics Inc.
|
|
* SPDX-License-Identifier: LicenseRef-LGE-Proprietary
|
|
*/
|
|
using Aurora.Api;
|
|
using Aurora.Api.DataType;
|
|
using PropertyTools.DataAnnotations;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
|
|
namespace VisionCommon {
|
|
/// <summary>
|
|
/// 카메라 디바이스 모델 리스트
|
|
/// </summary>
|
|
public enum eCamModel {
|
|
DEFAULT, // 공용 카메라 디바이스 사용 (AuroraVision에서 정의한 카메라 디바이스)
|
|
MachineCamera_A = 50, // 장비 전용 카메라 디바이스 A
|
|
MachineCamera_B, // 장비 전용 카메라 디바이스 B
|
|
MachineCamera_C // 장비 전용 카메라 디바이스 C
|
|
}
|
|
|
|
/// <summary>
|
|
/// 그래버 유형
|
|
/// </summary>
|
|
public enum eBoardType {
|
|
Mock, // Mock Camera
|
|
MIL_GIGE, // MIL GigE
|
|
MIL_CL_SOLIOS, // MIL CameraLink
|
|
MIL_CXP_RADIENT, // MIL CoaXPress
|
|
MIL_CXP_RAPIXO, // MIL CoaXPress
|
|
COGNEX_GIGE, // Cognex GigE
|
|
EURESYS_GIGELINK, // Euresys GigELink (With MIL Image Processing)
|
|
EURESYS_COAXLINK, // Euresys CoaxLink (With MIL Image Processing)
|
|
EURESYS_GRABLINK, // Euresys GrabLink (With MIL Image Processing)
|
|
}
|
|
|
|
/// <summary>
|
|
/// 그래버 슬롯 위치 (MIL에서 Auto 인덱싱 해줌에 주의)
|
|
/// </summary>
|
|
public enum eBoardSlotPos {
|
|
M_DEV0 = 0, // MIL - M_DEV0
|
|
M_DEV1 = 1, // MIL - M_DEV1
|
|
M_DEV2 = 2, // MIL - M_DEV2
|
|
M_DEV3 = 3, // MIL - M_DEV3
|
|
M_DEV4 = 4, // MIL - M_DEV4
|
|
M_DEV5 = 5, // MIL - M_DEV5
|
|
}
|
|
|
|
/// <summary>
|
|
/// 그래버 포트 위치 (MIL에서 Auto 인덱싱 해줌에 주의)
|
|
/// </summary>
|
|
public enum eBoardPortPos {
|
|
M_DEV0 = 0, // MIL - M_DEV0
|
|
M_DEV1 = 1, // MIL - M_DEV1
|
|
M_DEV2 = 2, // MIL - M_DEV2
|
|
M_DEV3 = 3, // MIL - M_DEV3
|
|
M_DEV4 = 4, // MIL - M_DEV4
|
|
M_DEV5 = 5, // MIL - M_DEV5
|
|
M_DEV6 = 6, // MIL - M_DEV6
|
|
M_DEV7 = 7 // MIL - M_DEV7
|
|
}
|
|
|
|
/// <summary>
|
|
/// 카메라 트리거 유형
|
|
/// </summary>
|
|
public enum eTrigType {
|
|
HW, // Hardware Trigger (External Trigger)
|
|
SW // Software Trigger (Internal Trigger)
|
|
}
|
|
|
|
/// <summary>
|
|
/// 카메라 트리거 발생 주체
|
|
/// </summary>
|
|
public enum eTrigSubject {
|
|
/// <summary>트리거 발생 주체가 외부(버퍼) 프로그램인 경우</summary>
|
|
External,
|
|
/// <summary>트리거 발생 주체가 Aurora인 경우</summary>
|
|
Internal
|
|
}
|
|
|
|
/// <summary>
|
|
/// GenICam "TriggerSource" Features
|
|
/// </summary>
|
|
public enum eTrigSrc {
|
|
Software,
|
|
Line0,
|
|
Line1,
|
|
Line2,
|
|
Line3,
|
|
Line4,
|
|
Line5,
|
|
LinkTrigger0, // 유레시스 용
|
|
LinkTrigger1, // 유레시스 용
|
|
LinkTrigger2, // 유레시스 용
|
|
LinkTrigger3, // 유레시스 용
|
|
LinkTrigger4, // 유레시스 용
|
|
LinkTrigger5, // 유레시스 용
|
|
CXPin,
|
|
}
|
|
|
|
public class CamConnConfig {
|
|
[SelectorStyle(SelectorStyle.ComboBox)]
|
|
public eBoardType BoardType { get; set; } = eBoardType.MIL_GIGE;
|
|
[SelectorStyle(SelectorStyle.ComboBox)]
|
|
public eBoardSlotPos BoardSlotPos { get; set; } = eBoardSlotPos.M_DEV0;
|
|
[SelectorStyle(SelectorStyle.ComboBox)]
|
|
public eBoardPortPos BoardPortPos { get; set; } = eBoardPortPos.M_DEV0;
|
|
/// <summary>
|
|
/// MIL : *.dcf 파일로 카메라 연결. EX) "D:\\Aurora\\DcfFiles\\CAM1.dcf"
|
|
/// Euresys : *.cti 파일로 카메라 연결. EX) "C:\\Program Files\\Euresys\\eGrabber\\cti\\x86_64\\gigelink.cti"
|
|
/// </summary>
|
|
[InputFilePath]
|
|
public string ConnFilePath { get; set; } = ""; // MIL DCF파일로 카메라를 연결할 경우 사용. EX) "D:\\Aurora\\DcfFiles\\CAM1.dcf"
|
|
public string IpAddress { get; set; } = ""; // GigE 고정 IP로 카메라를 연결할 경우 사용. EX) "100.100.200.10"
|
|
}
|
|
|
|
#region For Child Image Buffer
|
|
public class ChildBufRowCol : ICloneable {
|
|
public bool Enabled { get; set; } = true; // 버퍼 할당 유무
|
|
public int RowIdx { get; set; } = 0; // 행 인덱스
|
|
public int ColIdx { get; set; } = 0; // 열 인덱스
|
|
public int PosIdx { get; set; } = 0; // 위치 인덱스
|
|
public MotionPoint MotorPos { get; set; } = new MotionPoint(); // 모터 위치 X,Y
|
|
public MotionPoint MotorPosOffset { get; set; } = new MotionPoint(); // 모터 위치 오프셋 X,Y
|
|
public Rectangle Rect { get; set; } = new Rectangle(); // Child 이미지 영역 위치 & 사이즈
|
|
|
|
public object Clone() {
|
|
return new ChildBufRowCol() {
|
|
Enabled = this.Enabled,
|
|
RowIdx = this.RowIdx,
|
|
ColIdx = this.ColIdx,
|
|
PosIdx = this.PosIdx,
|
|
MotorPos = this.MotorPos.Clone() as MotionPoint,
|
|
MotorPosOffset = this.MotorPosOffset.Clone() as MotionPoint,
|
|
Rect = new Rectangle(this.Rect.X, this.Rect.Y, this.Rect.Width, this.Rect.Height)
|
|
};
|
|
}
|
|
}
|
|
|
|
public class ChildImage : ICloneable {
|
|
public bool Enabled { get; set; } = false; // Child 이미지 버퍼 사용 유무
|
|
public int RowCnt { get; set; } = 1; // 행 개수
|
|
public int ColCnt { get; set; } = 1; // 열 개수
|
|
public List<ChildBufRowCol> ChildBufRowCols { get; set; } = new List<ChildBufRowCol>(); // Child 이미지 버퍼 행/열 위치 정보
|
|
|
|
public object Clone() {
|
|
return new ChildImage() {
|
|
Enabled = this.Enabled,
|
|
RowCnt = this.RowCnt,
|
|
ColCnt = this.ColCnt,
|
|
ChildBufRowCols = this.ChildBufRowCols.ConvertAll(o => o.Clone() as ChildBufRowCol)
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// 활성화된 모터 위치 인덱스 기준으로 오름차순 정렬된 Child 객체 리스트 가져오기
|
|
/// </summary>
|
|
/// <returns>활성화된 모터 위치 인덱스 기준으로 오름차순 정렬된 Child 객체 리스트</returns>
|
|
public List<ChildBufRowCol> GetSortedChildBufRowCols() {
|
|
var childBufRowCol = this.ChildBufRowCols.Where(o => o.Enabled == true).OrderBy(o => o.PosIdx).ToList();
|
|
return childBufRowCol;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
public class FlipAndRotation : ICloneable {
|
|
public eImageFlip ImageFlip { get; set; } = eImageFlip.None; // 반전 (좌우 or 상하)
|
|
public eImageRotation ImageRotation { get; set; } = eImageRotation.None; // 회전 (0, 90, 180, 270)
|
|
public double ImageRotationOffset { get; set; } = 0; // 회전 ImageRotation을 기준으로 +/- 각도 Offset 적용
|
|
|
|
public object Clone() {
|
|
return new FlipAndRotation() {
|
|
ImageFlip = this.ImageFlip,
|
|
ImageRotation = this.ImageRotation,
|
|
ImageRotationOffset = this.ImageRotationOffset
|
|
};
|
|
}
|
|
}
|
|
|
|
public class SetupDirection : ICloneable {
|
|
public int RotationX { get; set; } = 0;
|
|
public eFlipY FlipY { get; set; } = eFlipY.False;
|
|
public eDirection DirectionT { get; set; } = eDirection.Plus;
|
|
|
|
public object Clone() {
|
|
return new SetupDirection() {
|
|
RotationX = this.RotationX,
|
|
FlipY = this.FlipY
|
|
};
|
|
}
|
|
|
|
public CoordSystem ToCoordSystem() {
|
|
return new CoordSystem(Angle.CreateWithDegree(RotationX), FlipY, DirectionT);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 취득을 위한 카메라 트리거 모드 관리
|
|
/// </summary>
|
|
public class TriggerMode : ICloneable {
|
|
public bool IsSoftware { get; set; } = true; // True : SW트리거 그랩 / False : HW트리거 그랩 (One-Shot 트리거 API 사용)
|
|
public bool IsExternal { get; set; } = false; // True : 외부 트리거 사용 / False : 외부 트리거 미사용 / *외부 : 버퍼 프로그램
|
|
public bool IsFlying { get; set; } = false; // True : Flying 그랩 사용 / False : Flying 그랩 미사용
|
|
|
|
public object Clone() {
|
|
return new TriggerMode() {
|
|
IsSoftware = this.IsSoftware,
|
|
IsExternal = this.IsExternal,
|
|
IsFlying = this.IsFlying
|
|
};
|
|
}
|
|
}
|
|
|
|
public class HwTrigConfig {
|
|
public eTrigSubject TrigSubject { get; set; } = eTrigSubject.Internal;
|
|
public int OutIdx { get; set; } = 5632; // FlexAttach CAM1 예시
|
|
public int OutPort { get; set; } = 22; // OutIdx에서 변환 가능 : (OutIdx & 0xFF00) >> 8
|
|
public int OutBit { get; set; } = 0; // OutIdx에서 변환 가능 : OutIdx & 0x00FF
|
|
public int OffDelay_Ms { get; set; } = 10;
|
|
public int ProcBufSize { get; set; } = 10; // HwTrigger CallBack 핸들러 버퍼 사이즈 (플라잉 모드시에는 플라잉 트리거 횟수로 사용)
|
|
}
|
|
|
|
public class CamConfig : IDeviceConfig, ICloneCopy<CamConfig> {
|
|
public string Name { get; set; } = string.Empty;
|
|
[SelectorStyle(SelectorStyle.ComboBox)]
|
|
public eCamModel CamModel { get; set; } = eCamModel.DEFAULT; // 공용 카메라 디바이스를 사용할지, 아니면 장비 전용 카메라 디바이스를 사용할지 결정
|
|
public IConnConfig ConnConfig { get; set; }
|
|
public CamConnConfig CamConnConfig { get; set; } = new CamConnConfig();
|
|
public eTrigSrc TrigSrc { get; set; } = eTrigSrc.Software;
|
|
public TriggerMode TriggerMode { get; set; } = new TriggerMode();
|
|
public HwTrigConfig HwTrigConfig { get; set; } = new HwTrigConfig();
|
|
public ImageSize ImageSize { get; set; }
|
|
public double ImageSizeRatioX { get; set; } = 1; // 원본 사이즈 대비 가로 비율. EX) 1이면 정사이즈, 0.5이면 1/2크기, RatioX,Y가 모두 0.5이면 이미지는 1/4크기가 됨.
|
|
public double ImageSizeRatioY { get; set; } = 1; // 원본 사이즈 대비 세로 비율. EX) 1이면 정사이즈, 0.5이면 1/2크기, RatioX,Y가 모두 0.5이면 이미지는 1/4크기가 됨.
|
|
public ChildImage ChildImage { get; set; } = new ChildImage();
|
|
public FlipAndRotation FlipAndRotation { get; set; } = new FlipAndRotation();
|
|
public double ExposureTime_Ms { get; set; } = 30; // 단위 : ms
|
|
public int LiveDelay_Ms { get; set; } = 50; // 단위 : ms
|
|
public int GrabRetry { get; set; } = 3;
|
|
public int GrabTimeout_Ms { get; set; } = 300; // 단위 : ms
|
|
public SetupDirection SetupDirection { get; set; } = new SetupDirection();
|
|
|
|
public static IDeviceConfig GetDefaultConfig() => new CamConfig();
|
|
|
|
public CamConfig() {
|
|
ImageSize = new ImageSize() {
|
|
Width = 2448, // 단위 : pixel
|
|
Height = 2048, // 단위 : pixel
|
|
Channel = 1, // 1 : Gray, 3 : Color(RGB)
|
|
BitDepth = 8 // 단위 : bit
|
|
};
|
|
}
|
|
|
|
public CamConfig Clone() {
|
|
return ((ICloneable)this).Clone() as CamConfig;
|
|
}
|
|
|
|
object ICloneable.Clone() {
|
|
var cloneObj = new CamConfig();
|
|
CopyTo(cloneObj);
|
|
return cloneObj;
|
|
}
|
|
|
|
public void CopyTo(CamConfig target) {
|
|
target.Name = this.Name;
|
|
target.CamConnConfig = new CamConnConfig() {
|
|
BoardType = this.CamConnConfig.BoardType,
|
|
BoardSlotPos = this.CamConnConfig.BoardSlotPos,
|
|
BoardPortPos = this.CamConnConfig.BoardPortPos,
|
|
ConnFilePath = this.CamConnConfig.ConnFilePath,
|
|
IpAddress = this.CamConnConfig.IpAddress
|
|
};
|
|
target.TrigSrc = this.TrigSrc;
|
|
target.TriggerMode = this.TriggerMode.Clone() as TriggerMode;
|
|
target.HwTrigConfig = new HwTrigConfig() {
|
|
TrigSubject = this.HwTrigConfig.TrigSubject,
|
|
OutIdx = this.HwTrigConfig.OutIdx,
|
|
OutPort = this.HwTrigConfig.OutPort,
|
|
OutBit = this.HwTrigConfig.OutBit,
|
|
OffDelay_Ms = this.HwTrigConfig.OffDelay_Ms,
|
|
ProcBufSize = this.HwTrigConfig.ProcBufSize,
|
|
};
|
|
target.ImageSize = new ImageSize() {
|
|
Width = this.ImageSize.Width,
|
|
Height = this.ImageSize.Height,
|
|
Channel = this.ImageSize.Channel,
|
|
BitDepth = this.ImageSize.BitDepth,
|
|
};
|
|
target.ImageSizeRatioX = this.ImageSizeRatioX;
|
|
target.ImageSizeRatioY = this.ImageSizeRatioY;
|
|
target.ChildImage = this.ChildImage.Clone() as ChildImage;
|
|
target.FlipAndRotation = this.FlipAndRotation.Clone() as FlipAndRotation;
|
|
target.ExposureTime_Ms = this.ExposureTime_Ms;
|
|
target.LiveDelay_Ms = this.LiveDelay_Ms;
|
|
target.GrabRetry = this.GrabRetry;
|
|
target.GrabTimeout_Ms = this.GrabTimeout_Ms;
|
|
target.SetupDirection = this.SetupDirection.Clone() as SetupDirection;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 항상 SW트리거로만 동작하는지 체크
|
|
/// </summary>
|
|
/// <returns>항상 SW트리거로 동작하면 True</returns>
|
|
public bool IsAlwaysSwTrigger() {
|
|
return TriggerMode.IsSoftware && !TriggerMode.IsExternal && !TriggerMode.IsFlying;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 항상 HW트리거로만 동작하는지 체크
|
|
/// </summary>
|
|
/// <returns>항상 HW트리거로 동작하면 True</returns>
|
|
public bool IsAlwaysHwTrigger() {
|
|
return !TriggerMode.IsSoftware;
|
|
}
|
|
}
|
|
}
|