1222 lines
45 KiB
C#
1222 lines
45 KiB
C#
/*
|
|
* Copyright (c) 2025 LG Electronics Inc.
|
|
* SPDX-License-Identifier: LicenseRef-LGE-Proprietary
|
|
*/
|
|
using Aurora;
|
|
using Aurora.Api;
|
|
using Aurora.Api.DataType;
|
|
using MilCommon;
|
|
using VisionCommon;
|
|
using Hermes;
|
|
using Matrox.MatroxImagingLibrary;
|
|
using System;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using VisionCommonUI;
|
|
using VisionCommonUI.Resources;
|
|
using Euresys.EGrabber;
|
|
using System.Collections.Generic;
|
|
|
|
namespace MilCamera {
|
|
/// <summary>
|
|
/// Euresys 모듈 정의
|
|
/// </summary>
|
|
public enum eModule {
|
|
Interface,
|
|
Device,
|
|
Remote,
|
|
Stream
|
|
}
|
|
|
|
/// <summary>
|
|
/// Euresys 카메라 디바이스 (영상처리는 MIL로 함)
|
|
/// </summary>
|
|
public class EuresysCamera : CameraBase {
|
|
#region Euresys Global Variables
|
|
private const uint GRAB_REQ_TIMEOUT_MS = 1000; // 1 sec
|
|
private const uint REALLOC_BUFFER_COUNT = 5;
|
|
private const ulong SINGLE_GRAB_COUNT = 1;
|
|
|
|
private EGrabber _eGrabber;
|
|
|
|
private Task _ProcessEventsTask;
|
|
private CancellationTokenSource _CancellationTokenSource;
|
|
|
|
private Euresys.EGrabber.Buffer _eLastBuffer;
|
|
private readonly object _eLastBufferLock = new object();
|
|
private byte[] _LastBufferArray = null;
|
|
|
|
private int _Width;
|
|
private int _Height;
|
|
private int _PixelSize;
|
|
private int _PixelComponentCount;
|
|
#endregion
|
|
|
|
private MIL_ID _OriginalImage = MIL.M_NULL; // 원본 이미지 버퍼
|
|
private MIL_ID _FilteredImage = MIL.M_NULL; // Flip + Rotation 이미지 버퍼
|
|
private MIL_ID _FilteredLiveImage = MIL.M_NULL; // Flip + Rotation 라이브 이미지 버퍼
|
|
private MIL_ID _CroppedImage = MIL.M_NULL; // Flip + Rotation + Crop 이미지 버퍼
|
|
private MIL_ID _CroppedLiveImage = MIL.M_NULL; // Flip + Rotation + Crop 라이브 이미지 버퍼
|
|
|
|
private IMilCameraDisplay _MilCameraDisplay; // Fov별로 가지는 MilCameraDisplay를 호출시마다 받아서 사용
|
|
private MilImgFlipAndRotationTool _MilImgFlipAndRotationTool;
|
|
|
|
/// <summary>
|
|
/// 생성자
|
|
/// </summary>
|
|
/// <param name="deviceId">디바이스 ID</param>
|
|
public EuresysCamera(string deviceId) : base(deviceId) {
|
|
var subject = string.Format("EuresysCamera[{0}]", deviceId);
|
|
LOG = new Logger(subject);
|
|
TactTimeChecker = new TactTimeChecker(subject);
|
|
}
|
|
|
|
protected override int DoActivate(IDeviceConfig config) {
|
|
if (IsActivated) {
|
|
LOG.FuncI("Already Activated!");
|
|
return E1.OK;
|
|
}
|
|
|
|
CamConfig = config as CamConfig;
|
|
eCamId camId = CamRecipe.GetCamIdFromDevId(DeviceId);
|
|
_MilImgFlipAndRotationTool = new MilImgFlipAndRotationTool(camId, CamConfig);
|
|
|
|
var res = Init();
|
|
if (res == E1.OK) {
|
|
CheckImageBufferRotationChanged();
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
#region Init
|
|
private int Init() {
|
|
MilEnvironment.Instance.AllocSys(CamConfig.CamConnConfig.BoardType, CamConfig.CamConnConfig.BoardSlotPos);
|
|
|
|
if (E1.OK != InitDigitizer()) {
|
|
MessageBoxUtil.ShowMessageBoxError(StrTokens.MSG_E_DigitizerInitError);
|
|
return E1.GENERIC;
|
|
}
|
|
if (E1.OK != SetImageSize()) {
|
|
MessageBoxUtil.ShowMessageBoxError(StrTokens.MSG_E_ImageSizeSettingError);
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
if (!MilEnvironment.Instance.HasValidLicense()) {
|
|
MessageBoxUtil.ShowMessageBoxError(StrTokens.MSG_E_NoMilLicense);
|
|
return E1.GENERIC;
|
|
}
|
|
if (E1.OK != AllocImages()) {
|
|
MessageBoxUtil.ShowMessageBoxError(StrTokens.MSG_E_ImageNotAllocated);
|
|
return E1.GENERIC;
|
|
}
|
|
if (E1.OK != SetTrigger()) {
|
|
MessageBoxUtil.ShowMessageBoxError(StrTokens.MSG_E_TriggerSettingError);
|
|
return E1.GENERIC;
|
|
}
|
|
if (E1.OK != SetExposureTimeFromConfig()) {
|
|
MessageBoxUtil.ShowMessageBoxError(StrTokens.MSG_E_ExposureTimeSettingError);
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
StartStream();
|
|
|
|
return E1.OK;
|
|
}
|
|
|
|
private int InitDigitizer() {
|
|
try {
|
|
// Euresys 보드를 사용하더라도 MIL API를 사용할 것이므로 eBoardType을 MIL_DEFAULT로 설정한다.
|
|
if (!EuresysEnvironment.IsEuresysBoardType(CamConfig.CamConnConfig.BoardType)) {
|
|
LOG.FuncE("BoardType is not EURESYS.");
|
|
return E1.ARGUMENT;
|
|
}
|
|
|
|
return InitDigitizerImpl();
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
}
|
|
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
private int InitDigitizerImpl() {
|
|
try {
|
|
InitEuresysGrabber();
|
|
|
|
if (EuresysGrabberManager.EGrabberDiscovery.CameraCount == 0) {
|
|
LOG.FuncE("No Camera Discovered.");
|
|
return E1.RESOURCE;
|
|
}
|
|
|
|
#region 참고 코드
|
|
// 방법 1
|
|
//int camIdx = 0;
|
|
//_eGrabber = new EGrabber(_eGrabberDiscovery.Cameras[camIdx]);
|
|
|
|
// 방법 2
|
|
//int grabberIdx = 0;
|
|
//EGrabberInfo info = _eGrabberDiscovery.GetGrabber(grabberIdx);
|
|
//_eGrabber = new EGrabber(info);
|
|
#endregion
|
|
|
|
int res = E1.GENERIC;
|
|
|
|
if (CamConfig.CamConnConfig.BoardType == eBoardType.EURESYS_GIGELINK) {
|
|
LOG.FuncI("Try connecting the camera by IP address.");
|
|
res = ConnectCameraByIpAddress();
|
|
}
|
|
if (res != E1.OK) {
|
|
LOG.FuncI("Try connecting the camera by geni-cam device user id.");
|
|
res = ConnectCameraByDeviceUserId();
|
|
}
|
|
if (res != E1.OK) {
|
|
LOG.FuncI("Try connecting the camera by slot and board pos.");
|
|
res = ConnectCameraBySlotAndPortPos();
|
|
}
|
|
if (res != E1.OK || _eGrabber == null) {
|
|
LOG.FuncE("Failed to connect camera.");
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
string card = _eGrabber.Interface.Get<string>("InterfaceID");
|
|
string dev = _eGrabber.Device.Get<string>("DeviceID");
|
|
_Width = (int)_eGrabber.Remote.Get<ulong>("Width");
|
|
_Height = (int)_eGrabber.Remote.Get<ulong>("Height");
|
|
_PixelSize = (int)_eGrabber.Stream.Get<ulong>("PixelSize");
|
|
_PixelComponentCount = (int)_eGrabber.Stream.Get<ulong>("PixelComponentCount");
|
|
|
|
LOG.FuncI($"Interface : {card}");
|
|
LOG.FuncI($"Device : {dev}");
|
|
LOG.FuncI($"Resolution : {_Width}x{_Height}");
|
|
LOG.FuncI($"PixelSize : {_PixelSize}");
|
|
LOG.FuncI($"PixelComponentCount : {_PixelComponentCount}");
|
|
|
|
_eGrabber.ReallocBuffers(REALLOC_BUFFER_COUNT);
|
|
_eGrabber.RegisterEventCallback<NewBufferData>(HookHandler);
|
|
_LastBufferArray = new byte[_Width * _Height];
|
|
|
|
return E1.OK;
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
}
|
|
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
private void InitEuresysGrabber() {
|
|
if (EuresysGrabberManager.IsCreated()) {
|
|
return;
|
|
}
|
|
|
|
if (!File.Exists(EuresysGrabberManager.CtiPath)) {
|
|
SetCtiFilePath();
|
|
}
|
|
|
|
if (File.Exists(EuresysGrabberManager.CtiPath)) {
|
|
LOG.FuncV($"Set a digitizer with a cti file. [{EuresysGrabberManager.CtiPath}]");
|
|
|
|
if (EuresysGrabberManager.Create(EuresysGrabberManager.CtiPath) != E1.OK) {
|
|
LOG.FuncE("Failed to create grabber.");
|
|
return;
|
|
}
|
|
}
|
|
else {
|
|
LOG.FuncE($"cti file is exists not. [{EuresysGrabberManager.CtiPath}]");
|
|
return;
|
|
}
|
|
}
|
|
|
|
private void SetCtiFilePath() {
|
|
if (CamConfig.CamConnConfig.ConnFilePath != string.Empty) {
|
|
EuresysGrabberManager.CtiPath = CamConfig.CamConnConfig.ConnFilePath; // Euresys의 경우 Cti 파일 경로 (Common Transport Interface)
|
|
}
|
|
else {
|
|
string ctiFileName = "gigelink.cti"; // Default
|
|
switch (CamConfig.CamConnConfig.BoardType) {
|
|
case eBoardType.EURESYS_COAXLINK:
|
|
ctiFileName = "coaxlink.cti";
|
|
break;
|
|
case eBoardType.EURESYS_GRABLINK:
|
|
ctiFileName = "grablink.cti";
|
|
break;
|
|
}
|
|
EuresysGrabberManager.CtiPath = string.Format(@"C:\\Program Files\\Euresys\\eGrabber\\cti\\x86_64\\{0}", ctiFileName);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// [방법1] GigE 카메라 고정 IP를 이용한 카메라 연결
|
|
/// </summary>
|
|
private int ConnectCameraByIpAddress() {
|
|
foreach (var grabberInfo in EuresysGrabberManager.EGrabberDiscovery.EGrabbers) {
|
|
if (CamConfig.CamConnConfig.IpAddress != String.Empty) {
|
|
_eGrabber = new EGrabber(grabberInfo);
|
|
var ipAddress = _eGrabber.Interface.Get<string>("DeviceCurrentIPAddress");
|
|
if (CamConfig.CamConnConfig.IpAddress == ipAddress) {
|
|
return E1.OK;
|
|
}
|
|
else {
|
|
_eGrabber?.Dispose();
|
|
_eGrabber = null;
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
/// <summary>
|
|
/// [방법2] GenI캠 DeviceUserId를 이용한 카메라 연결
|
|
/// </summary>
|
|
private int ConnectCameraByDeviceUserId() {
|
|
foreach (var grabberInfo in EuresysGrabberManager.EGrabberDiscovery.EGrabbers) {
|
|
if (CamConfig.Name != String.Empty) {
|
|
if (CamConfig.Name == grabberInfo.DeviceUserID) {
|
|
_eGrabber = new EGrabber(grabberInfo);
|
|
return E1.OK;
|
|
}
|
|
}
|
|
}
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
/// <summary>
|
|
/// [방법3] SlotPos와 PortPos를 이용한 카메라 연결
|
|
/// </summary>
|
|
private int ConnectCameraBySlotAndPortPos() {
|
|
foreach (var grabberInfo in EuresysGrabberManager.EGrabberDiscovery.EGrabbers) {
|
|
if ((int)CamConfig.CamConnConfig.BoardSlotPos == grabberInfo.InterfaceIndex &&
|
|
(int)CamConfig.CamConnConfig.BoardPortPos == grabberInfo.DeviceIndex) {
|
|
LOG.FuncI($"InterfaceIndex(SlotPos) : {grabberInfo.InterfaceIndex}");
|
|
LOG.FuncI($"DeviceIndex(PortPos) : {grabberInfo.DeviceIndex}");
|
|
_eGrabber = new EGrabber(grabberInfo);
|
|
return E1.OK;
|
|
}
|
|
}
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
private int SetImageSize() {
|
|
try {
|
|
CamConfig.ImageSize.Width = _Width;
|
|
CamConfig.ImageSize.Height = _Height;
|
|
CamConfig.ImageSize.Channel = _PixelComponentCount;
|
|
CamConfig.ImageSize.BitDepth = _PixelSize;
|
|
}
|
|
catch (Exception e) {
|
|
LOG.E(e.Message);
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
return E1.OK;
|
|
}
|
|
|
|
private int SetExposureTimeFromConfig() {
|
|
try {
|
|
SetExposure(CamConfig.ExposureTime_Ms);
|
|
}
|
|
catch (Exception e) {
|
|
LOG.E(e.Message);
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
return E1.OK;
|
|
}
|
|
|
|
protected int AllocImages() {
|
|
try {
|
|
var results = new List<int>();
|
|
results.Add(AllocOriginalImage(ref _OriginalImage));
|
|
results.Add(AllocFilteredImage(ref _FilteredImage));
|
|
results.Add(AllocFilteredImage(ref _FilteredLiveImage));
|
|
results.Add(AllocCroppedImage(ref _CroppedImage));
|
|
results.Add(AllocCroppedImage(ref _CroppedLiveImage));
|
|
results.AddRange(AllocProcImages());
|
|
|
|
foreach (int result in results) {
|
|
if (result != E1.OK) {
|
|
return E1.GENERIC;
|
|
}
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
LOG.E(e.Message);
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
return E1.OK;
|
|
}
|
|
|
|
private int AllocOriginalImage(ref MIL_ID image) {
|
|
return MilEnvironment.Instance.AllocOriginalImage(CamConfig, ref image);
|
|
}
|
|
|
|
private int AllocFilteredImage(ref MIL_ID image) {
|
|
return MilEnvironment.Instance.AllocFilteredImage(CamConfig, ref image);
|
|
}
|
|
|
|
private int AllocCroppedImage(ref MIL_ID image) {
|
|
return MilEnvironment.Instance.AllocCroppedImage(CamConfig, ref image);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 버퍼 복제
|
|
/// </summary>
|
|
/// <returns>복제 버퍼</returns>
|
|
public override object CloneImageBuffer() {
|
|
return MilEnvironment.CloneImage(_CroppedImage);
|
|
}
|
|
|
|
private int SetTrigger() {
|
|
try {
|
|
SetImmediateTrigger();
|
|
|
|
if (CamConfig.TriggerMode.IsSoftware) {
|
|
return SetSwTrigger();
|
|
}
|
|
else {
|
|
return SetHwTrigger();
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
return E1.GENERIC;
|
|
}
|
|
}
|
|
|
|
private void SetImmediateTrigger() {
|
|
eCamId camId = CamRecipe.GetCamIdFromDevId(DeviceId);
|
|
if (CameraFactory.GetBoardType(camId) != eBoardType.EURESYS_GIGELINK) {
|
|
SetFeatureString(eModule.Device, "CameraControlMethod", "RC"); // 무조건 RG, RC이어야 Set이 됨. NC이면 잠겨서 설정 안됨.
|
|
//SetFeatureString(eModule.Device, "CameraControlMethod", "RG"); // 무조건 RG, RC이어야 Set이 됨. NC이면 잠겨서 설정 안됨.
|
|
SetFeatureString(eModule.Device, "ExposureReadoutOverlap", "True");
|
|
SetFeatureDouble(eModule.Device, "ExposureRecoveryTime", 100); // [us]
|
|
}
|
|
|
|
SetFeatureString(eModule.Remote, "TriggerMode", "On");
|
|
SetFeatureString(eModule.Remote, "TriggerSelector", "FrameStart");
|
|
//SetFeatureString(eModule.Remote, "TriggerOverlap", "ReadOut"); // "RG"일 때만 해당
|
|
SetFeatureString(eModule.Remote, "ExposureMode", "Timed"); // "RC"일 때만 해당. "Timed" : 카메라에서 노출 제어(RC)
|
|
//SetFeatureString(eModule.Remote, "ExposureMode", "TriggerWidth"); // "RG"일 때만 해당. "TriggerWidth" : 보드에서 노출 제어(RG)
|
|
}
|
|
|
|
private int SetHwTrigger() {
|
|
try {
|
|
// 인터페이스 I/O 설정
|
|
SetFeatureString(eModule.Interface, "LineInputToolSelector", "LIN1");
|
|
SetFeatureString(eModule.Interface, "LineInputToolSource", "IIN11");
|
|
|
|
// 프레임 그래버 설정
|
|
eCamId camId = CamRecipe.GetCamIdFromDevId(DeviceId);
|
|
if (CameraFactory.GetBoardType(camId) != eBoardType.EURESYS_GIGELINK) {
|
|
SetFeatureString(eModule.Device, "CycleTriggerSource", "LIN1");
|
|
SetFeatureDouble(eModule.Device, "CycleMinimumPeriod", 4200); // 카메라 fps의 역수보다 약간 크게 입력해야 함 [us]
|
|
}
|
|
|
|
// 카메라 설정
|
|
SetFeatureString(eModule.Remote, "TriggerSource", CamConfig.TrigSrc.ToString()); // 카메라 제조사마다 다름.. Line0 ??
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
return E1.OK;
|
|
}
|
|
|
|
private int SetSwTrigger() {
|
|
try {
|
|
// 프레임 그래버 설정
|
|
eCamId camId = CamRecipe.GetCamIdFromDevId(DeviceId);
|
|
if (CameraFactory.GetBoardType(camId) != eBoardType.EURESYS_GIGELINK) {
|
|
SetFeatureString(eModule.Device, "CycleTriggerSource", "Immediate"); // 사이클 주기마다 반복 수행
|
|
//SetFeatureString(eModule.Device, "CycleTriggerSource", "StartCycle"); // 요청 올때만 수행
|
|
SetFeatureDouble(eModule.Device, "CycleMinimumPeriod", 30000); // 카메라 fps의 역수보다 약간 크게 입력해야 함 [us]
|
|
}
|
|
|
|
// 카메라 설정
|
|
SetFeatureString(eModule.Remote, "TriggerSource", CamConfig.TrigSrc.ToString());
|
|
SetFeatureString(eModule.Remote, "TriggerMode", "Off");
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
return E1.OK;
|
|
}
|
|
|
|
private void SetFeatureString(eModule module, string featureName, string writeValue) {
|
|
try {
|
|
string readValue = string.Empty;
|
|
|
|
switch (module) {
|
|
case eModule.Interface:
|
|
_eGrabber.Interface.Set<string>(featureName, writeValue);
|
|
readValue = _eGrabber.Interface.Get<string>(featureName);
|
|
break;
|
|
case eModule.Device:
|
|
_eGrabber.Device.Set<string>(featureName, writeValue);
|
|
readValue = _eGrabber.Device.Get<string>(featureName);
|
|
break;
|
|
case eModule.Remote:
|
|
_eGrabber.Remote.Set<string>(featureName, writeValue);
|
|
readValue = _eGrabber.Remote.Get<string>(featureName);
|
|
break;
|
|
case eModule.Stream:
|
|
_eGrabber.Stream.Set<string>(featureName, writeValue);
|
|
readValue = _eGrabber.Stream.Get<string>(featureName);
|
|
break;
|
|
}
|
|
|
|
if (!writeValue.Equals(readValue)) {
|
|
LOG.E($"module : {module} / featureName : {featureName} / writeValue: {writeValue} / readValue : {readValue}");
|
|
}
|
|
else {
|
|
LOG.I($"module : {module} / featureName : {featureName} / writeValue: {writeValue} / readValue : {readValue}");
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
LOG.FuncE($"module : {module} / featureName : {featureName} / writeValue: {writeValue}");
|
|
}
|
|
}
|
|
|
|
private void SetFeatureDouble(eModule module, string featureName, double writeValue) {
|
|
try {
|
|
double readValue = -1;
|
|
|
|
switch (module) {
|
|
case eModule.Interface:
|
|
_eGrabber.Interface.Set<double>(featureName, writeValue);
|
|
readValue = _eGrabber.Interface.Get<double>(featureName);
|
|
break;
|
|
case eModule.Device:
|
|
_eGrabber.Device.Set<double>(featureName, writeValue);
|
|
readValue = _eGrabber.Device.Get<double>(featureName);
|
|
break;
|
|
case eModule.Remote:
|
|
_eGrabber.Remote.Set<double>(featureName, writeValue);
|
|
readValue = _eGrabber.Remote.Get<double>(featureName);
|
|
break;
|
|
case eModule.Stream:
|
|
_eGrabber.Stream.Set<double>(featureName, writeValue);
|
|
readValue = _eGrabber.Stream.Get<double>(featureName);
|
|
break;
|
|
}
|
|
|
|
if (!writeValue.Equals(readValue)) {
|
|
LOG.E($"module : {module} / featureName : {featureName} / writeValue: {writeValue} / readValue : {readValue}");
|
|
}
|
|
else {
|
|
LOG.I($"module : {module} / featureName : {featureName} / writeValue: {writeValue} / readValue : {readValue}");
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
LOG.FuncE($"module : {module} / featureName : {featureName} / writeValue: {writeValue}");
|
|
}
|
|
}
|
|
|
|
private int StartStream() {
|
|
try {
|
|
_eGrabber?.EnableEvent(EventType.NewBufferData);
|
|
_eGrabber?.Start();
|
|
_CancellationTokenSource = new CancellationTokenSource();
|
|
_ProcessEventsTask = _eGrabber.ProcessEventsAsync(EventType.NewBufferData, _CancellationTokenSource.Token);
|
|
|
|
return E1.OK;
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
return E1.GENERIC;
|
|
}
|
|
}
|
|
|
|
private int StopStream() {
|
|
try {
|
|
_eGrabber?.Stop();
|
|
_eGrabber?.DisableEvent(EventType.NewBufferData);
|
|
_CancellationTokenSource?.Cancel();
|
|
_ProcessEventsTask?.Wait();
|
|
_ProcessEventsTask = null;
|
|
_CancellationTokenSource?.Dispose();
|
|
_CancellationTokenSource = null;
|
|
|
|
if (_eLastBuffer != null) {
|
|
_eLastBuffer.Push();
|
|
_eLastBuffer.Dispose();
|
|
_eLastBuffer = null;
|
|
}
|
|
_eGrabber?.FlushEvent(EventType.All);
|
|
|
|
return E1.OK;
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
return E1.GENERIC;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
protected override int DoDeactivate() {
|
|
if (!IsActivated) {
|
|
LOG.I("Already Deactivated!");
|
|
return E1.OK;
|
|
}
|
|
|
|
return Dispose();
|
|
}
|
|
|
|
#region Dispose
|
|
private int Dispose() {
|
|
try {
|
|
StopStream();
|
|
StopBufLive();
|
|
StopMdigProcess();
|
|
FreeImages();
|
|
|
|
_LastBufferArray = null;
|
|
|
|
_eLastBuffer?.Dispose();
|
|
_eLastBuffer = null;
|
|
|
|
_eGrabber?.Dispose();
|
|
_eGrabber = null;
|
|
|
|
return E1.OK;
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
}
|
|
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
private void StopBufLive() {
|
|
if (!IsActivated)
|
|
return;
|
|
|
|
try {
|
|
lock (LockThis) {
|
|
StopLive();
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
LOG.E(e.Message);
|
|
}
|
|
}
|
|
|
|
private void FreeImages() {
|
|
try {
|
|
MilEnvironment.FreeImage(_OriginalImage);
|
|
MilEnvironment.FreeImage(_FilteredImage);
|
|
MilEnvironment.FreeImage(_FilteredLiveImage);
|
|
MilEnvironment.FreeImage(_CroppedImage);
|
|
MilEnvironment.FreeImage(_CroppedLiveImage);
|
|
MilEnvironment.FreeImage(_ParentImage);
|
|
|
|
int bufSize = CamConfig.ChildImage.Enabled ? CamConfig.ChildImage.ChildBufRowCols.Count : CamConfig.HwTrigConfig.ProcBufSize;
|
|
MilEnvironment.FreeProcImages(bufSize, _ProcImages);
|
|
}
|
|
catch (Exception e) {
|
|
LOG.E(e.Message);
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// 카메라 연결 유무
|
|
/// </summary>
|
|
/// <returns>연결 유무</returns>
|
|
public override bool IsConnected() {
|
|
//MIL_INT isConnected = 0;
|
|
//MIL.MdigInquire(_Digitizer, MIL.M_CAMERA_PRESENT, ref isConnected);
|
|
//return (isConnected == MIL.M_YES);
|
|
return IsActivated;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 카메라 Gain 읽기
|
|
/// </summary>
|
|
/// <returns>Gain 값</returns>
|
|
public override int GetGain() => throw new NotImplementedException();
|
|
|
|
/// <summary>
|
|
/// 카메라 Gain 쓰기
|
|
/// </summary>
|
|
/// <param name="gain">Gain 값</param>
|
|
/// <returns>성공 유무</returns>
|
|
public override int SetGain(int gain) => throw new NotImplementedException();
|
|
|
|
/// <summary>
|
|
/// 카메라 노출시간 읽기
|
|
/// </summary>
|
|
/// <returns>노출시간</returns>
|
|
public override double GetExposure() {
|
|
if (_eGrabber == null) {
|
|
return E2.NOT_READY;
|
|
}
|
|
|
|
var exposureTime = _eGrabber.Remote.Get<ulong>("ExposureTime");
|
|
return exposureTime;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 카메라 최소 노출시간 읽기
|
|
/// </summary>
|
|
/// <returns>최소 노출시간</returns>
|
|
public override double GetMinExposure() => throw new NotImplementedException();
|
|
|
|
/// <summary>
|
|
/// 카메라 최대 노출시간 읽기
|
|
/// </summary>
|
|
/// <returns>최대 노출시간</returns>
|
|
public override double GetMaxExposure() => throw new NotImplementedException();
|
|
|
|
/// <summary>
|
|
/// 카메라 노출시간 쓰기
|
|
/// </summary>
|
|
/// <param name="exposureTime_ms">노출시간[ms]</param>
|
|
/// <returns>성공 유무</returns>
|
|
public override int SetExposure(double exposureTime_ms) {
|
|
if (!IsConnected()) {
|
|
return E2.NOT_READY;
|
|
}
|
|
|
|
var exposureTime_us = MathUtil.ConvertUnitMilliToMicro(exposureTime_ms);
|
|
SetFeatureDouble(eModule.Remote, "ExposureTime", exposureTime_us);
|
|
LOG.I($"Exposure Time Set : {exposureTime_ms} ms");
|
|
|
|
return E1.OK;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 반전 & 회전 Config 갱신
|
|
/// </summary>
|
|
/// <param name="flipAndRotation">이미지 반전 & 회전 Config</param>
|
|
/// <returns>성공 유무</returns>
|
|
public override int ResetFlipAndRotation(FlipAndRotation flipAndRotation) {
|
|
_MilImgFlipAndRotationTool?.ResetFlipAndRotation(flipAndRotation);
|
|
return E1.OK;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 디스플레이 가져오기
|
|
/// </summary>
|
|
/// <returns>디스플레이</returns>
|
|
public override ICameraDisplay GetDisplay() {
|
|
return _MilCameraDisplay;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 디스플레이 지정하기
|
|
/// </summary>
|
|
/// <param name="cameraDisplay">디스플레이</param>
|
|
public override void SetDisplay(ICameraDisplay cameraDisplay) {
|
|
_MilCameraDisplay = cameraDisplay as IMilCameraDisplay;
|
|
_MilCameraDisplay.SetVisibility();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이미지 사이즈 가져오기
|
|
/// </summary>
|
|
/// <returns>이미지 사이즈</returns>
|
|
public override ImageSize GetImageSize() {
|
|
return MilEnvironment.Instance.GetImageSize(CamConfig);
|
|
}
|
|
|
|
#region Grab
|
|
/// <summary>
|
|
/// 버퍼로부터 이미지를 꺼내온다.
|
|
/// </summary>
|
|
/// <param name="cameraDisplay">디스플레이</param>
|
|
/// <param name="image">이미지</param>
|
|
/// <returns>성공 유무</returns>
|
|
public override int GetGrabImageFromBuffer(ICameraDisplay cameraDisplay, ref object image) {
|
|
SetDisplay(cameraDisplay as IMilCameraDisplay);
|
|
return GetGrabImage(ref image, isExtTrig : true);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 동기식 그랩
|
|
/// </summary>
|
|
/// <param name="cameraDisplay">디스플레이</param>
|
|
/// <param name="image">그랩 이미지</param>
|
|
/// <returns>성공 유무</returns>
|
|
public override int GrabSync(ICameraDisplay cameraDisplay, ref object image) {
|
|
SetDisplay(cameraDisplay as IMilCameraDisplay);
|
|
MilEnvironment.ClearImage(_OriginalImage);
|
|
|
|
if (CamConfig.TriggerMode.IsSoftware) {
|
|
return GrabSync_SwTrig(ref image);
|
|
}
|
|
else {
|
|
return GrabSync_HwTrig(ref image);
|
|
}
|
|
}
|
|
|
|
private int GrabSync_HwTrig(ref object image) {
|
|
for (int i = 1; i <= CamConfig.GrabRetry; i++) {
|
|
int res = GrabSync_HwTrig_Internal(ref image);
|
|
if (res == E1.OK) {
|
|
return E1.OK;
|
|
}
|
|
LOG.I($"Grab Retry : {i}");
|
|
}
|
|
LOG.E("Grab Fail");
|
|
|
|
return E1.OK;
|
|
}
|
|
|
|
private int GrabSync_HwTrig_Internal(ref object image) {
|
|
try {
|
|
SetHookCompleted(false);
|
|
|
|
TriggerOn();
|
|
Thread.Sleep(CamConfig.HwTrigConfig.OffDelay_Ms);
|
|
TriggerOff();
|
|
|
|
return GetGrabImage(ref image, isExtTrig: false);
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
}
|
|
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
/// <summary>
|
|
/// SW 트리거의 경우 HookHandler에서 이미지가 계속 갱신되고 있으므로, 가져가기만 하면 됨
|
|
/// </summary>
|
|
/// <param name="grabImage">이미지</param>
|
|
/// <returns>성공 유무</returns>
|
|
private int GrabSync_SwTrig(ref object image) {
|
|
try {
|
|
//SetHookCompleted(false);
|
|
|
|
//ClearBuffers();
|
|
|
|
#region Grab 방식
|
|
//_eGrabber.ProcessEvent(EventType.NewBufferData, GRAB_REQ_TIMEOUT_MS); // [1] ProcessEvent (주문형 콜백)
|
|
//NewBufferData data = _eGrabber.Pop(GRAB_REQ_TIMEOUT_MS);
|
|
//PopOneOfResult rawData = _eGrabber.PopOneOf(EventType.NewBufferData, 3000); // [2] PopOneOf
|
|
//NewBufferData data = rawData.EventData as NewBufferData;
|
|
//NewBufferData data = _eGrabber.Pop(3000); // [3] Pop
|
|
//NewBufferData data = _eGrabber.GetBufferData(REALLOC_BUFFER_COUNT - 1); // [4] GetBufferData
|
|
#endregion
|
|
|
|
//lock (_eLastBufferLock) {
|
|
// if (_eLastBuffer != null) {
|
|
// // push back the last buffer
|
|
// _eLastBuffer.Push();
|
|
// _eLastBuffer.Dispose();
|
|
// _eLastBuffer = null;
|
|
// }
|
|
//}
|
|
|
|
return GetGrabImage(ref image, isExtTrig: false);
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
}
|
|
|
|
//TactTimeChecker.Stop(TactTimeType.Grab, "GrabSyncWithFiltering");
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
private void ClearBuffers() {
|
|
int remainBuffers = (int)_eGrabber.Stream.GetInfo<ulong>(STREAM_INFO_CMD.STREAM_INFO_NUM_AWAIT_DELIVERY);
|
|
while (Convert.ToBoolean(remainBuffers)) {
|
|
using (ScopedBuffer scopeBuffer = new ScopedBuffer(_eGrabber, 10)) {
|
|
remainBuffers--;
|
|
}
|
|
}
|
|
}
|
|
|
|
private int GetGrabImage(ref object image, bool isExtTrig) {
|
|
var stopWatch = Stopwatch.StartNew();
|
|
while (stopWatch.ElapsedMilliseconds < CamConfig.GrabTimeout_Ms) {
|
|
bool hookCompleted = isExtTrig ? IsHookCompletedByExtTrig() : IsHookCompleted();
|
|
if (hookCompleted) {
|
|
LOG.W($"Grab Completed : {stopWatch.ElapsedMilliseconds} ms");
|
|
|
|
FlipAndRotateImage();
|
|
CropImage();
|
|
SetDisplayImage();
|
|
|
|
image = IsLiveOn() ? _CroppedLiveImage : _CroppedImage;
|
|
|
|
return E1.OK;
|
|
}
|
|
Thread.Sleep(10);
|
|
}
|
|
|
|
LOG.E($"HookHandler Time Out!! [{CamConfig.GrabTimeout_Ms} ms] ");
|
|
return E1.GENERIC;
|
|
}
|
|
#endregion
|
|
|
|
#region Live
|
|
/// <summary>
|
|
/// 라이브 시작
|
|
/// </summary>
|
|
/// <param name="cameraDisplay">디스플레이</param>
|
|
public override void StartLive(ICameraDisplay cameraDisplay) {
|
|
if (_FilteredLiveImage == MIL.M_NULL) {
|
|
MessageBoxUtil.ShowMessageBoxError(string.Format(StrTokens.MSG_E_SomethingNotAllocated, "_FilteredLiveImage"));
|
|
return;
|
|
}
|
|
|
|
lock (_LiveLock) {
|
|
// 이미 라이브가 실행중이면, 디스플레이만 변경한다.
|
|
SetDisplay(cameraDisplay);
|
|
|
|
if (!IsLiveOn()) {
|
|
LiveOn();
|
|
if (CamConfig.TriggerMode.IsSoftware) {
|
|
Task.Run(() => { StartLive_SwTrig(); });
|
|
}
|
|
else {
|
|
Task.Run(() => { StartLive_HwTrig(); });
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 라이브 종료
|
|
/// </summary>
|
|
public override void StopLive() {
|
|
lock (_LiveLock) {
|
|
if (IsLiveOn()) {
|
|
LiveOff();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void StartLive_HwTrig() {
|
|
try {
|
|
while (IsLiveOn()) {
|
|
SetHookCompleted(false);
|
|
|
|
TriggerOn();
|
|
Thread.Sleep(CamConfig.HwTrigConfig.OffDelay_Ms);
|
|
TriggerOff();
|
|
|
|
var stopWatch = Stopwatch.StartNew();
|
|
while (stopWatch.ElapsedMilliseconds < CamConfig.GrabTimeout_Ms) {
|
|
if (IsHookCompleted()) {
|
|
FlipAndRotateImage();
|
|
CropImage();
|
|
SetDisplayImage();
|
|
break;
|
|
}
|
|
Thread.Sleep(10);
|
|
}
|
|
//Thread.Sleep(CamConfig.LiveDelay);
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
}
|
|
}
|
|
|
|
private void StartLive_SwTrig() {
|
|
try {
|
|
while (IsLiveOn()) {
|
|
var image = (object)_FilteredLiveImage;
|
|
GrabSync(_MilCameraDisplay as IMilCameraDisplay, ref image);
|
|
_FilteredLiveImage = (MIL_ID)image;
|
|
Thread.Sleep(CamConfig.LiveDelay_Ms);
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
private void TriggerOn() {
|
|
try {
|
|
EquipAdapter.Instance.EquipTrigger.TriggerOn(CamConfig);
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
}
|
|
}
|
|
|
|
private void TriggerOff() {
|
|
try {
|
|
EquipAdapter.Instance.EquipTrigger.TriggerOff(CamConfig);
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 디스플레이에서 이미지 꺼내오기
|
|
/// </summary>
|
|
/// <param name="cameraDisplay">디스플레이</param>
|
|
/// <returns>디스플레이 이미지</returns>
|
|
public override object GetImageFromDisplay(ICameraDisplay cameraDisplay) {
|
|
// 버퍼 그랩 이후, 디스플레이로부터 이미지를 꺼내오는 부분
|
|
// 이미지를 꺼내오기 전에 cameraDisplay와 동일한 _MilCameraDisplay가 사전에 Set되어 있어야 함.
|
|
var milCameraDisplay = cameraDisplay as IMilCameraDisplay;
|
|
if (milCameraDisplay.IsSetImage()) {
|
|
return milCameraDisplay.GetImage();
|
|
}
|
|
|
|
LOG.FuncE("Image of milCameraDisplay is null.");
|
|
return MIL.M_NULL;
|
|
}
|
|
|
|
/// <summary>
|
|
/// EventCallBack 함수 (SW 트리거 일때는 계속 들어오고, HW 트리거 일때는 신호가 터질 때만 들어옴)
|
|
/// </summary>
|
|
/// <param name="g">그래버</param>
|
|
/// <param name="data">Raw 데이터</param>
|
|
private void HookHandler(EGrabber g, NewBufferData data) {
|
|
try {
|
|
PrintHookLog();
|
|
|
|
lock (_eLastBufferLock) {
|
|
if (_eLastBuffer != null) {
|
|
// push back the last buffer
|
|
_eLastBuffer.Push();
|
|
_eLastBuffer.Dispose();
|
|
_eLastBuffer = null;
|
|
}
|
|
_eLastBuffer = new Euresys.EGrabber.Buffer(g, data);
|
|
Marshal.Copy(_eLastBuffer.Pixels, _LastBufferArray, 0, _Width * _Height);
|
|
MilEnvironment.ConvertByteArryToMil(_LastBufferArray, _Width, _Height, ref _OriginalImage);
|
|
}
|
|
|
|
SetHookCompleted(true);
|
|
if (CamConfig.TriggerMode.IsExternal) {
|
|
SetHookCompletedByExtTrig(true);
|
|
}
|
|
SetFlyingImage();
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
}
|
|
}
|
|
|
|
private void PrintHookLog() {
|
|
if (!IsLiveOn()) {
|
|
LOG.FuncV("[HW Trigger] HookHandler Called.");
|
|
}
|
|
}
|
|
|
|
#region For Hw Trigger
|
|
private List<int> AllocProcImages() {
|
|
var results = new List<int>();
|
|
|
|
if (!CamConfig.IsAlwaysSwTrigger()) {
|
|
if (_ProcImages?.Length > 0) {
|
|
MilEnvironment.FreeProcImages(_ProcImages.Length, _ProcImages);
|
|
}
|
|
|
|
if (CamConfig.ChildImage.Enabled) {
|
|
results.Add(MilEnvironment.Instance.AllocParentImage(CamConfig, ref _ParentImage));
|
|
results.Add(MilEnvironment.Instance.AllocChildImages(CamConfig, _ParentImage, ref _ProcImages));
|
|
}
|
|
else {
|
|
_ProcImages = new object[CamConfig.HwTrigConfig.ProcBufSize];
|
|
results.Add(MilEnvironment.Instance.AllocProcImages(CamConfig, CamConfig.HwTrigConfig.ProcBufSize, ref _ProcImages));
|
|
}
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
private void StartMdigProcess() {
|
|
try {
|
|
//_HookData.HookDigitizer = _Digitizer;
|
|
//_HookData.HookImage = _OriginalImage;
|
|
//_HookData.HookCnt = 0;
|
|
|
|
//if (!_UserDataHandle.IsAllocated) {
|
|
// _UserDataHandle = GCHandle.Alloc(_HookData);
|
|
//}
|
|
//if (_HookFuncPtr == null) {
|
|
// _HookFuncPtr = new MIL_DIG_HOOK_FUNCTION_PTR(HookHandler);
|
|
//}
|
|
|
|
//MIL.MdigControlFeature(_Digitizer, MIL.M_FEATURE_VALUE_AS_STRING, "AcquisitionMode", MIL.M_DEFAULT, "Continuous"); // SingleFrame 아니어도 되나..?
|
|
//MIL.MdigControlFeature(_Digitizer, MIL.M_FEATURE_VALUE_AS_STRING, "TriggerMode", MIL.M_DEFAULT, "On");
|
|
//MIL.MdigControlFeature(_Digitizer, MIL.M_FEATURE_VALUE_AS_STRING, "TriggerSource", MIL.M_DEFAULT, CamConfig.TrigSrc.ToString());
|
|
|
|
//if (_ProcImages != null) {
|
|
// MIL.MdigProcess(
|
|
// _Digitizer, Array.ConvertAll(_ProcImages, item => (MIL_ID)item), (MIL_INT)_ProcImages.Length, MIL.M_START, MIL.M_DEFAULT, _HookFuncPtr, GCHandle.ToIntPtr(_UserDataHandle));
|
|
//}
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
}
|
|
}
|
|
|
|
private void StopMdigProcess() {
|
|
try {
|
|
//MIL.MdigControl(_Digitizer, MIL.M_PROCESS_TIMEOUT, 5);
|
|
//if (_ProcImages?.Length > 0) {
|
|
// //MIL.MdigProcess(_Digitizer, _ProcImages, (MIL_INT)_ProcImages.Length, MIL.M_STOP, MIL.M_DEFAULT, _HookFuncPtr, GCHandle.ToIntPtr(_UserDataHandle)); // 원래 코드
|
|
// MIL.MdigProcess(
|
|
// _Digitizer, Array.ConvertAll(_ProcImages, item => (MIL_ID)item), (MIL_INT)_ProcImages.Length, MIL.M_STOP + MIL.M_WAIT, MIL.M_SYNCHRONOUS, _HookFuncPtr, GCHandle.ToIntPtr(_UserDataHandle));
|
|
//}
|
|
//if (_UserDataHandle.IsAllocated)
|
|
// _UserDataHandle.Free();
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region For Flying
|
|
/// <summary>
|
|
/// 플라잉 시작
|
|
/// </summary>
|
|
/// <param name="fovInfo">FOV 정보</param>
|
|
/// <param name="param">추가 파라미터</param>
|
|
/// <returns>성공 유무</returns>
|
|
public override int StartFlying(FovInfo fovInfo, object param) {
|
|
if (IsFlyingRunning()) {
|
|
LOG.FuncW("Flying Already Running...");
|
|
return E1.GENERIC;
|
|
}
|
|
LOG.I("Flying Start.");
|
|
|
|
try {
|
|
var camDisplay = CameraDisplayManager.GetDisplay(fovInfo);
|
|
SetDisplay(camDisplay);
|
|
|
|
_FlyingIdx = 0;
|
|
_IsFlyingRunning = true;
|
|
|
|
StartMdigProcess();
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
return E1.GENERIC;
|
|
}
|
|
return E1.OK;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 플라잉 종료
|
|
/// </summary>
|
|
/// <param name="param">추가 파라미터</param>
|
|
/// <returns>성공 유무</returns>
|
|
public override int StopFlying(object param = null) {
|
|
LOG.I("Flying Stopped.");
|
|
|
|
try {
|
|
_IsFlyingRunning = false;
|
|
StopMdigProcess();
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
return E1.GENERIC;
|
|
}
|
|
return E1.OK;
|
|
}
|
|
|
|
private void SetFlyingImage() {
|
|
if (!CamConfig.TriggerMode.IsFlying) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
FlipAndRotateImage();
|
|
CropImage();
|
|
|
|
_FlyingIdx = (_FlyingIdx < _ProcImages.Length) ? _FlyingIdx : 0;
|
|
MilEnvironment.CopyImage(_CroppedImage, (MIL_ID)_ProcImages[_FlyingIdx++]);
|
|
SetDisplayImage();
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region For Child Image
|
|
/// <summary>
|
|
/// Child 이미지들로 Parent(원장) 이미지가 정상적으로 만들어지는지 검증
|
|
/// </summary>
|
|
/// <param name="cameraDisplay">디스플레이</param>
|
|
/// <param name="image">원장(부모) 이미지</param>
|
|
/// <returns>성공 유무</returns>
|
|
public override int VerifyChildImage(ICameraDisplay cameraDisplay, ref object image) {
|
|
try {
|
|
return E1.OK;
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
}
|
|
return E1.GENERIC;
|
|
}
|
|
#endregion
|
|
|
|
private void SetDisplayImage() {
|
|
if (_MilCameraDisplay == null) {
|
|
return;
|
|
}
|
|
|
|
if (IsLiveOn()) {
|
|
if (_CroppedLiveImage != null) {
|
|
_MilCameraDisplay.SetImage(_CroppedLiveImage);
|
|
}
|
|
}
|
|
else {
|
|
if (_CroppedImage != null) {
|
|
_MilCameraDisplay.SetImage(_CroppedImage);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void FlipAndRotateImage() {
|
|
if (_OriginalImage == null) {
|
|
LOG.FuncE("_OriginalImage is null.");
|
|
return;
|
|
}
|
|
|
|
if (IsLiveOn()) {
|
|
_MilImgFlipAndRotationTool.FlipAndRotation(_OriginalImage, ref _FilteredLiveImage);
|
|
}
|
|
else {
|
|
_MilImgFlipAndRotationTool.FlipAndRotation(_OriginalImage, ref _FilteredImage);
|
|
}
|
|
}
|
|
|
|
private void CropImage() {
|
|
var cropRoi = GetCropRoi();
|
|
if (IsLiveOn()) {
|
|
if (_FilteredLiveImage != null) {
|
|
_CroppedLiveImage = MilEnvironment.CropImage(_FilteredLiveImage, cropRoi);
|
|
}
|
|
}
|
|
else {
|
|
if (_FilteredImage != null) {
|
|
_CroppedImage = MilEnvironment.CropImage(_FilteredImage, cropRoi);
|
|
}
|
|
}
|
|
}
|
|
|
|
private class HookDataStruct {
|
|
public MIL_ID HookDigitizer;
|
|
public MIL_ID HookImage;
|
|
public int HookCnt;
|
|
}
|
|
}
|
|
} |