1239 lines
45 KiB
C#
1239 lines
45 KiB
C#
using Aurora;
|
|
using Aurora.Api;
|
|
using Aurora.Api.DataType;
|
|
using Hermes;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using VisionCommon;
|
|
using VisionCommonUI;
|
|
using VisionCommonUI.Resources;
|
|
|
|
#if USE_COGNEX
|
|
using Cognex.VisionPro;
|
|
using CogCamera;
|
|
using CogCommon;
|
|
|
|
// Cognex인 경우 여기에 구현
|
|
// ...
|
|
#else
|
|
using Matrox.MatroxImagingLibrary;
|
|
using MilCamera;
|
|
using MilCommon;
|
|
|
|
namespace WeldingCommon.Vision.Camera {
|
|
/// <summary>
|
|
/// 장비 카메라 디바이스 A (클래스 이름 변경 금지)
|
|
/// 장비에 맞게 변경하여 사용한다.
|
|
/// 아래 코드는 레이저 스캐너 용접기 전용 카메라로 사용된다.
|
|
/// </summary>
|
|
public class MachineCamera_A : CameraBase {
|
|
private MIL_ID _Digitizer = MIL.M_NULL;
|
|
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;
|
|
|
|
private readonly object _SwTrigLock = new object();
|
|
|
|
#region For Hw Trigger
|
|
private const int GRAB_HANDLER_WAITING_TIME = 250; // GrabHandler에 들어올 때까지 기다리는 최대 시간 (ms) -> 버퍼 그랩의 경우 기다릴 필요X
|
|
private MIL_ID[] MilProcImages = null; // SW트리거 콜백용
|
|
private GCHandle _UserDataHandle;
|
|
private HookDataStruct _HookData = new HookDataStruct();
|
|
private MIL_DIG_HOOK_FUNCTION_PTR _HookFuncPtr = null;
|
|
#endregion
|
|
|
|
#region For RCC Flying
|
|
private GCHandle _FlyingUserDataHandle;
|
|
private HookDataStruct _FlyingHookData = new HookDataStruct();
|
|
private MIL_DIG_HOOK_FUNCTION_PTR _FlyingHookFuncPtr = null;
|
|
#endregion
|
|
|
|
public MachineCamera_A(string deviceId) : base(deviceId) {
|
|
var subject = string.Format("MachineCamera_A[{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;
|
|
}
|
|
|
|
private void CheckImageBufferRotationChanged() {
|
|
if (OldRatioX != CamConfig.ImageSizeRatioX ||
|
|
OldRatioY != CamConfig.ImageSizeRatioY ||
|
|
OldRotationType != CamConfig.FlipAndRotation.ImageRotation) {
|
|
|
|
OldRatioX = CamConfig.ImageSizeRatioX;
|
|
OldRatioY = CamConfig.ImageSizeRatioY;
|
|
OldRotationType = CamConfig.FlipAndRotation.ImageRotation;
|
|
|
|
VisionEnv.AuroraEnv.EventPublisher.Publish(
|
|
new EventMessage(DeviceId, VisionEventId.UPDATE_GRAB_IMAGE_BUFFER));
|
|
}
|
|
}
|
|
|
|
#region Init
|
|
private int Init() {
|
|
MilEnvironment.Instance.AllocSys(CamConfig.CamConnConfig.BoardType, CamConfig.CamConnConfig.BoardSlotPos);
|
|
|
|
if (!MilEnvironment.Instance.HasValidLicense()) {
|
|
MessageBoxUtil.ShowMessageBoxError(StrTokens.MSG_E_NoMilLicense);
|
|
return E1.GENERIC;
|
|
}
|
|
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 (E1.OK != AllocImages()) {
|
|
MessageBoxUtil.ShowMessageBoxError(StrTokens.MSG_E_ImageNotAllocated);
|
|
return E1.GENERIC;
|
|
}
|
|
if (E1.OK != SetExposureTimeFromConfig()) {
|
|
MessageBoxUtil.ShowMessageBoxError(StrTokens.MSG_E_ExposureTimeSettingError);
|
|
return E1.GENERIC;
|
|
}
|
|
if (E1.OK != StartGrabMdigProcess()) {
|
|
MessageBoxUtil.ShowMessageBoxError(StrTokens.MSG_E_TriggerSettingError);
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
return E1.OK;
|
|
}
|
|
|
|
private int InitDigitizer() {
|
|
try {
|
|
if (CamConfig.CamConnConfig.ConnFilePath != string.Empty) {
|
|
if (File.Exists(CamConfig.CamConnConfig.ConnFilePath)) {
|
|
LOG.FuncV($"Set a digitizer with a dcf file. [{CamConfig.CamConnConfig.ConnFilePath}]");
|
|
InitDigitizerWithDcf();
|
|
}
|
|
else {
|
|
LOG.FuncE("Dcf file is exists not.");
|
|
return E2.NOT_FOUND;
|
|
}
|
|
}
|
|
else {
|
|
LOG.FuncV("Set a digitizer without a dcf file.");
|
|
InitDigitizerWithoutDcf(); // DcfFilePath가 공백이면, Dcf파일 없이 Digitizer 할당.
|
|
}
|
|
|
|
if (_Digitizer != MIL.M_NULL) {
|
|
MIL.MdigControl(_Digitizer, MIL.M_GRAB_ABORT, MIL.M_DEFAULT);
|
|
MIL.MdigControl(_Digitizer, MIL.M_GRAB_MODE, MIL.M_ASYNCHRONOUS);
|
|
MIL.MdigControl(_Digitizer, MIL.M_AUTO_EXPOSURE, MIL.M_DISABLE);
|
|
|
|
return E1.OK;
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
}
|
|
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
private void InitDigitizerWithDcf() {
|
|
try {
|
|
MIL.MdigAlloc(
|
|
MilEnvironment.Instance.GetSystem(CamConfig.CamConnConfig.BoardType, CamConfig.CamConnConfig.BoardSlotPos),
|
|
(int)CamConfig.CamConnConfig.BoardPortPos,
|
|
CamConfig.CamConnConfig.ConnFilePath,
|
|
MIL.M_DEFAULT,
|
|
ref _Digitizer);
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
}
|
|
}
|
|
|
|
private void InitDigitizerWithoutDcf() {
|
|
try {
|
|
if (CamConfig.CamConnConfig.BoardType == eBoardType.MIL_GIGE) {
|
|
MIL.MdigAlloc(
|
|
MilEnvironment.Instance.GetSystem(CamConfig.CamConnConfig.BoardType, CamConfig.CamConnConfig.BoardSlotPos),
|
|
MIL.M_GC_CAMERA_ID(CamConfig.CamConnConfig.IpAddress),
|
|
"M_DEFAULT",
|
|
MIL.M_GC_DEVICE_IP_ADDRESS,
|
|
ref _Digitizer);
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
}
|
|
}
|
|
|
|
private int SetImageSize() {
|
|
MIL_INT width = 0;
|
|
MIL_INT height = 0;
|
|
MIL_INT band = 0;
|
|
MIL_INT bitDepth = 0;
|
|
|
|
try {
|
|
MIL.MdigInquire(_Digitizer, MIL.M_SIZE_X, ref width);
|
|
MIL.MdigInquire(_Digitizer, MIL.M_SIZE_Y, ref height);
|
|
MIL.MdigInquire(_Digitizer, MIL.M_SIZE_BAND, ref band);
|
|
MIL.MdigInquire(_Digitizer, MIL.M_SIZE_BIT, ref bitDepth);
|
|
|
|
CamConfig.ImageSize.Width = (int)width;
|
|
CamConfig.ImageSize.Height = (int)height;
|
|
CamConfig.ImageSize.Channel = (int)band;
|
|
CamConfig.ImageSize.BitDepth = (int)bitDepth;
|
|
}
|
|
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);
|
|
}
|
|
|
|
private int SetExposureTimeFromConfig() {
|
|
try {
|
|
SetInitialExposure();
|
|
SetExposure(CamConfig.ExposureTime_Ms);
|
|
}
|
|
catch (Exception e) {
|
|
LOG.E(e.Message);
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
return E1.OK;
|
|
}
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// 이미지 버퍼 복제
|
|
/// </summary>
|
|
/// <returns>복제 버퍼</returns>
|
|
public override object CloneImageBuffer() {
|
|
return MilEnvironment.CloneImage(_CroppedImage);
|
|
}
|
|
|
|
private int StartGrabMdigProcess() {
|
|
try {
|
|
lock (LockThis) {
|
|
// Grab과 Live는 SW Trigger만 사용한다.
|
|
SetSwTrigger();
|
|
|
|
_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.MdigProcess(_Digitizer, MilProcImages, (MIL_INT)MilProcImages.Length, MIL.M_START, MIL.M_DEFAULT, _HookFuncPtr, GCHandle.ToIntPtr(_UserDataHandle));
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
return E1.OK;
|
|
}
|
|
|
|
private int SetSwTrigger() {
|
|
try {
|
|
lock (LockThis) {
|
|
if (CamConfig.CamConnConfig.BoardType == eBoardType.MIL_CXP_RAPIXO) {
|
|
//FlyingVision
|
|
MIL.MdigControl(_Digitizer, MIL.M_TIMER1 + MIL.M_TIMER_STATE, MIL.M_DISABLE);
|
|
MIL.MdigControl(_Digitizer, MIL.M_TIMER1 + MIL.M_TIMER_TRIGGER_SOURCE, MIL.M_SOFTWARE);
|
|
MIL.MdigControl(_Digitizer, MIL.M_TIMER1 + MIL.M_TIMER_STATE, MIL.M_ENABLE);
|
|
}
|
|
else if (CamConfig.CamConnConfig.BoardType == eBoardType.MIL_GIGE) {
|
|
// GigE
|
|
MIL.MdigControl(_Digitizer, MIL.M_GRAB_TRIGGER_STATE, MIL.M_ENABLE);
|
|
MIL.MdigControl(_Digitizer, MIL.M_GRAB_TRIGGER_SOURCE, MIL.M_SOFTWARE);
|
|
|
|
}
|
|
else {
|
|
LOG.E("Check Cam BoardType.");
|
|
}
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
return E1.OK;
|
|
}
|
|
|
|
private int SetHwTrigger() {
|
|
try {
|
|
lock (LockThis) {
|
|
// TODO : HW Trigger 설정 확인 필요
|
|
//MIL.MdigControlFeature(_Digitizer, MIL.M_FEATURE_VALUE_AS_STRING, "TriggerSource", MIL.M_DEFAULT, "Line0");
|
|
//MIL.MdigControlFeature(_Digitizer, MIL.M_FEATURE_VALUE_AS_STRING, "AcquisitionMode", MIL.M_DEFAULT, "Continuous");
|
|
//MIL.MdigControlFeature(_Digitizer, MIL.M_FEATURE_VALUE_AS_STRING, "TriggerMode", MIL.M_DEFAULT, "On");
|
|
MIL.MdigControl(_Digitizer, MIL.M_TIMER1 + MIL.M_TIMER_STATE, MIL.M_DISABLE);
|
|
|
|
MIL.MdigControl(_Digitizer, MIL.M_GRAB_ABORT, MIL.M_DEFAULT);
|
|
|
|
MIL.MdigControl(_Digitizer, MIL.M_TIMER1 + MIL.M_TIMER_STATE, MIL.M_EDGE_RISING);
|
|
MIL.MdigControl(_Digitizer, MIL.M_TIMER1 + MIL.M_TIMER_TRIGGER_SOURCE, MIL.M_AUX_IO2);
|
|
MIL.MdigControl(_Digitizer, MIL.M_TIMER1 + MIL.M_TIMER_STATE, MIL.M_ENABLE);
|
|
|
|
//MIL.MdigControl(_Digitizer, MIL.M_TIMER_TRIGGER_SOURCE, MIL.M_AUX_IO2);
|
|
|
|
//MIL.MdigControl(_Digitizer, MIL.M_GRAB_TRIGGER_STATE, MIL.M_ENABLE);
|
|
//MIL.MdigControl(_Digitizer, MIL.M_TIMER_TRIGGER_SOURCE, MIL.M_AUX_IO2);
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
return E1.OK;
|
|
}
|
|
|
|
private int AllocProcImage(ref MIL_ID[] milProcImages) {
|
|
try {
|
|
if (milProcImages == null) {
|
|
milProcImages = new MIL_ID[CamConfig.HwTrigConfig.ProcBufSize];
|
|
}
|
|
|
|
return AllocGrayProcImage(ref milProcImages);
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
}
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
private int AllocGrayProcImage(ref MIL_ID[] milProcImages) {
|
|
for (int i = 0; i < CamConfig.HwTrigConfig.ProcBufSize; i++) {
|
|
MIL.MbufAlloc2d(
|
|
MilEnvironment.Instance.GetSystem(CamConfig.CamConnConfig.BoardType, CamConfig.CamConnConfig.BoardSlotPos),
|
|
CamConfig.ImageSize.Width,
|
|
CamConfig.ImageSize.Height,
|
|
8 + MIL.M_UNSIGNED,
|
|
MIL.M_IMAGE + MIL.M_GRAB + MIL.M_PROC + MIL.M_DISP,
|
|
ref milProcImages[i]);
|
|
MIL.MbufClear(milProcImages[i], 0);
|
|
}
|
|
|
|
return E1.OK;
|
|
}
|
|
|
|
private void FreeProcImage(ref MIL_ID[] milProcImages) {
|
|
try {
|
|
if (milProcImages == null) {
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < milProcImages.Length; i++) {
|
|
MilEnvironment.FreeImage(milProcImages[i]);
|
|
milProcImages[i] = MIL.M_NULL;
|
|
}
|
|
milProcImages = null;
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
return;
|
|
}
|
|
}
|
|
|
|
protected override int DoDeactivate() {
|
|
if (!IsActivated) {
|
|
LOG.I("Already Deactivated!");
|
|
return E1.OK;
|
|
}
|
|
|
|
return Dispose();
|
|
}
|
|
|
|
#region Dispose
|
|
private int Dispose() {
|
|
try {
|
|
StopBufLive();
|
|
|
|
StopGrabMdigProcess();
|
|
|
|
#region For RCC Flying
|
|
StopFlyingMdigProcess();
|
|
SetFlyingStart(false);
|
|
#endregion
|
|
|
|
FreeImages();
|
|
|
|
if (_Digitizer != MIL.M_NULL) {
|
|
MIL.MdigFree(_Digitizer);
|
|
_Digitizer = MIL.M_NULL;
|
|
}
|
|
|
|
// MIL Sys와 App은 할당 후, 런타임 중에 해지하지 않고 쓰기로 함.
|
|
//MilEnvironment.Instance.Dispose();
|
|
|
|
return E1.OK;
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
}
|
|
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
private void StopBufLive() {
|
|
if (!IsActivated)
|
|
return;
|
|
|
|
try {
|
|
lock (LockThis) {
|
|
LiveOff();
|
|
MIL.MdigHalt(_Digitizer);
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
LOG.E(e.Message);
|
|
}
|
|
}
|
|
|
|
private void StopGrabMdigProcess() {
|
|
try {
|
|
lock (LockThis) {
|
|
if (MilProcImages?.Length > 0) {
|
|
MIL.MdigControl(_Digitizer, MIL.M_PROCESS_TIMEOUT, 5);
|
|
//MIL.MdigProcess(_Digitizer, MilProcImages, (MIL_INT)MilProcImages.Length, MIL.M_STOP + MIL.M_WAIT, MIL.M_DEFAULT, _HookFuncPtr, GCHandle.ToIntPtr(_UserDataHandle));
|
|
MIL.MdigProcess(_Digitizer, MilProcImages, (MIL_INT)MilProcImages.Length, MIL.M_STOP, MIL.M_DEFAULT, _HookFuncPtr, GCHandle.ToIntPtr(_UserDataHandle));
|
|
}
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
}
|
|
}
|
|
|
|
private void FreeImages() {
|
|
try {
|
|
MilEnvironment.FreeImage(_OriginalImage);
|
|
MilEnvironment.FreeImage(_FilteredImage);
|
|
MilEnvironment.FreeImage(_FilteredLiveImage);
|
|
MilEnvironment.FreeImage(_CroppedImage);
|
|
MilEnvironment.FreeImage(_CroppedLiveImage);
|
|
|
|
FreeProcImage(ref MilProcImages);
|
|
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
|
|
|
|
public override bool IsConnected() {
|
|
MIL_INT isConnected = 0;
|
|
MIL.MdigInquire(_Digitizer, MIL.M_CAMERA_PRESENT, ref isConnected);
|
|
|
|
return (isConnected == MIL.M_YES);
|
|
}
|
|
|
|
public override int GetGain() => throw new NotImplementedException();
|
|
public override int SetGain(int gain) => throw new NotImplementedException();
|
|
|
|
public override double GetMinExposure() {
|
|
if (!IsActivated) {
|
|
return E2.NOT_READY;
|
|
}
|
|
|
|
double exposureTime = 0;
|
|
MIL.MdigInquire(_Digitizer, MIL.M_EXPOSURE_TIME + MIL.M_MIN_VALUE, ref exposureTime);
|
|
return (int)(exposureTime / 1_000);
|
|
}
|
|
|
|
public override double GetMaxExposure() {
|
|
if (!IsActivated) {
|
|
return E2.NOT_READY;
|
|
}
|
|
|
|
//CXP 카메라 사용 시 ExposurteTime 못받아와서 하드코딩해둠
|
|
//double exposureTime = 5000 * 1000;
|
|
double exposureTime = 0;
|
|
MIL.MdigInquire(_Digitizer, MIL.M_EXPOSURE_TIME + MIL.M_MAX_VALUE, ref exposureTime);
|
|
return (int)(exposureTime / 1_000);
|
|
}
|
|
|
|
#region For Custumizing
|
|
private double _InitialExposureTime_Ms = 0; // 최초 노출시간 (ms)
|
|
|
|
/// <summary>
|
|
/// 카메라로부터 최초 노출시간 가져오기
|
|
/// 현재 노출시간은 아니고, 프로그램 시작시 DCF파일로부터 읽은 값임.
|
|
/// </summary>
|
|
/// <returns>최초 노출시간(ms)</returns>
|
|
public double GetInitialExposure() {
|
|
if (!IsActivated) {
|
|
return E2.NOT_READY;
|
|
}
|
|
|
|
return _InitialExposureTime_Ms;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 카메라로부터 최초 노출시간 가져오기 (현재 노출시간은 아님)
|
|
/// </summary>
|
|
/// <returns>성공 유무</returns>
|
|
private int SetInitialExposure() {
|
|
if (!IsActivated) {
|
|
return E2.NOT_READY;
|
|
}
|
|
|
|
_InitialExposureTime_Ms = GetExposure();
|
|
return E1.OK;
|
|
}
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// 카메라로부터 현재 노출시간 가져오기
|
|
/// </summary>
|
|
/// <returns>노출시간(ms)</returns>
|
|
public override double GetExposure() {
|
|
if (!IsActivated) {
|
|
return E2.NOT_READY;
|
|
}
|
|
|
|
double exposureTime = 0;
|
|
MIL.MdigInquire(_Digitizer, MIL.M_EXPOSURE_TIME, ref exposureTime);
|
|
return (int)(exposureTime / 1_000);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 카메라 노출시간 쓰기. GigE 카메라가 아닌 경우 HW에서 설정해주어야 함. (MIL에서 지원X)
|
|
/// </summary>
|
|
/// <param name="exposureTime_ms">노출시간[ms]</param>
|
|
/// <returns>성공 유무</returns>
|
|
public override int SetExposure(double exposureTime_ms) {
|
|
if (!IsConnected()) {
|
|
return E2.NOT_READY;
|
|
}
|
|
// [원래 코드]
|
|
//MIL.MdigControl(_Digitizer, MIL.M_EXPOSURE_TIME, (double)(exposureTime * 1_000));
|
|
|
|
var exposureTime_us = MathUtil.ConvertUnitMilliToMicro(exposureTime_ms);
|
|
MIL.MdigControlFeature(_Digitizer, MIL.M_FEATURE_VALUE_AS_STRING, "ExposureTime", MIL.M_DEFAULT, exposureTime_us.ToString());
|
|
//MIL.MdigControl(_Digitizer, MIL.M_EXPOSURE_TIME, exposureTime_us); // GigE에만 해당, 특정 HW에서는 동작하지 않았음.
|
|
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;
|
|
}
|
|
|
|
/// <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);
|
|
MilEnvironment.ClearImage(image);
|
|
MilEnvironment.ClearImage(_OriginalImage);
|
|
|
|
return GetGrabImage(ref image, isExtTrig: true);
|
|
}
|
|
|
|
public override int GrabSync(ICameraDisplay cameraDisplay, ref object image) {
|
|
SetDisplay(cameraDisplay as IMilCameraDisplay);
|
|
MilEnvironment.ClearImage(image);
|
|
MilEnvironment.ClearImage(_OriginalImage);
|
|
|
|
return GrabSync_SwTrig(ref image);
|
|
}
|
|
|
|
private int GrabSync_SwTrig(ref object image) {
|
|
try {
|
|
lock (_SwTrigLock) {
|
|
SetHookCompleted(false);
|
|
SwTriggerOn();
|
|
|
|
return GetGrabImage(ref image, isExtTrig: false);
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
}
|
|
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
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) {
|
|
// TODO : Live 실행 시 연속 Log 발생으로 주석 처리
|
|
//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
|
|
public override void StartLive(ICameraDisplay cameraDisplay) {
|
|
if (_CroppedLiveImage == MIL.M_NULL) {
|
|
MessageBoxUtil.ShowMessageBoxError(string.Format(StrTokens.MSG_E_SomethingNotAllocated, "_CroppedLiveImage"));
|
|
return;
|
|
}
|
|
|
|
lock (_LiveLock) {
|
|
// 이미 라이브가 실행중이면, 디스플레이만 변경한다.
|
|
SetDisplay(cameraDisplay);
|
|
|
|
if (!IsLiveOn()) {
|
|
LiveOn();
|
|
Task.Run(() => { StartLive_SwTrig(); });
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void StopLive() {
|
|
LiveOff();
|
|
}
|
|
|
|
private void StartLive_SwTrig() {
|
|
try {
|
|
object tmpImage = null; // 라이브때 리턴 이미지는 필요X
|
|
|
|
while (IsLiveOn()) {
|
|
GrabSync(_MilCameraDisplay, ref tmpImage);
|
|
Thread.Sleep(CamConfig.LiveDelay_Ms);
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
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;
|
|
}
|
|
|
|
private MIL_INT HookHandler(MIL_INT HookType, MIL_ID HookId, IntPtr HookDataPtr) {
|
|
try {
|
|
PrintHookLog(HookId);
|
|
|
|
//MIL_ID MilBufferId = MIL.M_NULL;
|
|
MIL.MdigGetHookInfo(HookId, MIL.M_MODIFIED_BUFFER + MIL.M_BUFFER_ID, ref _OriginalImage);
|
|
//MIL.MbufCopy(MilBufferId, _OriginalImage); // 중복 Copy 제거
|
|
|
|
SetHookCompleted(true);
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
return E1.OK;
|
|
}
|
|
|
|
// 플라잉 이미지 밀림 방지를 위해 Handler를 따로 씀.
|
|
private MIL_INT FlyingHookHandler(MIL_INT HookType, MIL_ID HookId, IntPtr HookDataPtr) {
|
|
try {
|
|
//MIL_ID MilBufferId = MIL.M_NULL;
|
|
//MIL.MdigGetHookInfo(HookId, MIL.M_MODIFIED_BUFFER + MIL.M_BUFFER_ID, ref MilBufferId);
|
|
MIL_ID MilBufferIndex = MIL.M_NULL;
|
|
MIL.MdigGetHookInfo(HookId, MIL.M_MODIFIED_BUFFER + MIL.M_BUFFER_INDEX, ref MilBufferIndex);
|
|
LOG.D($"MilBufferIndex : {MilBufferIndex}");
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
return E1.OK;
|
|
}
|
|
|
|
private void PrintHookLog(MIL_ID hookId) {
|
|
if (!IsLiveOn()) {
|
|
MIL_ID hookBufferIndex = MIL.M_NULL;
|
|
MIL.MdigGetHookInfo(hookId, MIL.M_MODIFIED_BUFFER + MIL.M_BUFFER_INDEX, ref hookBufferIndex);
|
|
LOG.D($"Hook Buffer Index : {hookBufferIndex}");
|
|
}
|
|
}
|
|
|
|
private void PrintFrameLog() {
|
|
try {
|
|
//MIL_INT frameCnt = 0;
|
|
//MIL.MdigInquire(_Digitizer, MIL.M_PROCESS_FRAME_COUNT, ref frameCnt);
|
|
|
|
double frameRate = 0;
|
|
MIL.MdigInquire(_Digitizer, MIL.M_PROCESS_FRAME_RATE, ref frameRate);
|
|
LOG.FuncI(string.Format("Frame Rate : {0:0.0} [f/s]", frameRate));
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
}
|
|
}
|
|
|
|
#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 {
|
|
SetDisplay(cameraDisplay);
|
|
|
|
foreach (ChildBufRowCol childBufRowCol in CamConfig.ChildImage.ChildBufRowCols) {
|
|
if (!childBufRowCol.Enabled) {
|
|
continue;
|
|
}
|
|
|
|
SetExposure((childBufRowCol.PosIdx + 1) * 5);
|
|
Thread.Sleep(50);
|
|
object childImage = null;
|
|
GrabSync(_MilCameraDisplay, ref childImage);
|
|
|
|
if (_ProcImages.Length > childBufRowCol.PosIdx) {
|
|
MilEnvironment.CopyImage((MIL_ID)childImage, (MIL_ID)_ProcImages[childBufRowCol.PosIdx]);
|
|
}
|
|
else {
|
|
LOG.FuncE("[ERROR] _ProcImages.Length <= childBufRowCol.PosIdx");
|
|
}
|
|
}
|
|
image = GetParentImage();
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
#region For RCC Flying
|
|
private List<int> AllocProcImages() {
|
|
var results = new List<int>();
|
|
|
|
AllocProcImage(ref MilProcImages); // SW트리거 콜백용
|
|
|
|
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));
|
|
}
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
private void AllocFlyingImage(ref MIL_ID flyingImage, int row, int col) {
|
|
try {
|
|
if (!IsFlyingEnabled()) {
|
|
return;
|
|
}
|
|
|
|
if (flyingImage != MIL.M_NULL) {
|
|
MilEnvironment.FreeImage(flyingImage);
|
|
}
|
|
|
|
int flyingImageWidth = CamConfig.ImageSize.Width * col;
|
|
int flyingImageHeight = CamConfig.ImageSize.Height * row;
|
|
|
|
MIL.MbufAlloc2d(
|
|
MilEnvironment.Instance.GetSystem(CamConfig.CamConnConfig.BoardType, CamConfig.CamConnConfig.BoardSlotPos),
|
|
flyingImageWidth,
|
|
flyingImageHeight,
|
|
8 + MIL.M_UNSIGNED,
|
|
MIL.M_IMAGE + MIL.M_GRAB + MIL.M_PROC + MIL.M_DISP,
|
|
ref flyingImage);
|
|
|
|
if (flyingImage == MIL.M_NULL) {
|
|
LOG.FuncE($"_FlyingImage is null");
|
|
return;
|
|
}
|
|
|
|
MIL.MbufClear(flyingImage, 0);
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
return;
|
|
}
|
|
}
|
|
|
|
private void FreeFlyingImage(ref MIL_ID flyingImage) {
|
|
try {
|
|
if (!IsFlyingEnabled()) {
|
|
return;
|
|
}
|
|
|
|
MilEnvironment.FreeImage(flyingImage);
|
|
flyingImage = MIL.M_NULL;
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
return;
|
|
}
|
|
}
|
|
|
|
private int AllocFlyingChildImages(
|
|
MIL_ID flyingImage, ref MIL_ID[] flyingChildImages) {
|
|
try {
|
|
if (!IsFlyingEnabled()) {
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
if (IsFlyingStart()) {
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
if (flyingImage == MIL.M_NULL) {
|
|
LOG.FuncE($"flyingImage is null");
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
if (flyingChildImages == null) {
|
|
flyingChildImages = new MIL_ID[CamConfig.ChildImage.ChildBufRowCols.Count];
|
|
for (int i = 0; i < flyingChildImages.Length; i++) {
|
|
flyingChildImages[i] = MIL.M_NULL;
|
|
}
|
|
}
|
|
|
|
int width = CamConfig.ImageSize.Width;
|
|
int height = CamConfig.ImageSize.Height;
|
|
|
|
for (int i = 0; i < CamConfig.ChildImage.ChildBufRowCols.Count; i++) {
|
|
int col = CamConfig.ChildImage.ChildBufRowCols[i].ColIdx;
|
|
int row = CamConfig.ChildImage.ChildBufRowCols[i].RowIdx;
|
|
int offsetX = col * width;
|
|
int offsetY = row * height;
|
|
|
|
//LOG.D($"({row}, {col}) : {offsetX}, {offsetY}");
|
|
|
|
if (flyingChildImages[i] != MIL.M_NULL) {
|
|
MilEnvironment.FreeImage(flyingChildImages[i]);
|
|
}
|
|
MIL.MbufChild2d(flyingImage, offsetX, offsetY, width, height, ref flyingChildImages[i]);
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
return E1.OK;
|
|
}
|
|
|
|
private void FreeFlyingChildImages(ref MIL_ID[] flyingChildImages) {
|
|
try {
|
|
if (!IsFlyingEnabled()) {
|
|
return;
|
|
}
|
|
|
|
if (flyingChildImages == null) {
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < flyingChildImages.Length; i++) {
|
|
MilEnvironment.FreeImage(flyingChildImages[i]);
|
|
flyingChildImages[i] = MIL.M_NULL;
|
|
}
|
|
flyingChildImages = null;
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 플라잉 종료
|
|
/// </summary>
|
|
/// <param name="param">추가 파라미터</param>
|
|
/// <returns>성공 유무</returns>
|
|
public override int StopFlying(object param = null) {
|
|
if (!IsActivated || !IsFlyingEnabled()) {
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
try {
|
|
lock (LockThis) {
|
|
if (!IsFlyingStart()) {
|
|
return E1.OK;
|
|
}
|
|
|
|
StopFlyingMdigProcess();
|
|
StartGrabMdigProcess();
|
|
SetFlyingStart(false);
|
|
|
|
var sw = Stopwatch.StartNew();
|
|
LOG.I($"T/T Flip Start");
|
|
for (int i = 0; i < _ProcImages.Length; i++) {
|
|
var childImg = (MIL_ID)_ProcImages[i];
|
|
_MilImgFlipAndRotationTool.FlipAndRotation(childImg, ref childImg); // 회전 불필요
|
|
//var cropRoi = GetCropRoi(); // Crop 불필요
|
|
//childImg = MilEnvironment.CropImage(childImg, cropRoi);
|
|
}
|
|
sw.Stop();
|
|
LOG.I($"T/T Flip : {sw.ElapsedMilliseconds} ms");
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
return E1.GENERIC;
|
|
}
|
|
return E1.OK;
|
|
}
|
|
|
|
private int StopFlyingMdigProcess() {
|
|
try {
|
|
lock (LockThis) {
|
|
if (!IsFlyingEnabled()) {
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
MIL.MdigControl(_Digitizer, MIL.M_PROCESS_TIMEOUT, 5);
|
|
|
|
// [원래 코드]
|
|
//MIL.MdigProcess(_Digitizer, _FlyingChildImages, (MIL_INT)_FlyingChildImages.Length, MIL.M_STOP + MIL.M_WAIT, MIL.M_SYNCHRONOUS, _FlyingHookFuncPtr, GCHandle.ToIntPtr(_FlyingUserDataHandle));
|
|
|
|
if (_ProcImages?.Length > 0) {
|
|
//MIL.MdigProcess(_Digitizer, Array.ConvertAll(_ProcImages, item => (MIL_ID)item), (MIL_INT)_ProcImages.Length, MIL.M_STOP + MIL.M_WAIT, MIL.M_SYNCHRONOUS, _FlyingHookFuncPtr, GCHandle.ToIntPtr(_FlyingUserDataHandle));
|
|
MIL.MdigProcess(_Digitizer, Array.ConvertAll(_ProcImages, item => (MIL_ID)item), (MIL_INT)_ProcImages.Length, MIL.M_STOP, MIL.M_SYNCHRONOUS, _FlyingHookFuncPtr, GCHandle.ToIntPtr(_FlyingUserDataHandle));
|
|
}
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
return E1.GENERIC;
|
|
}
|
|
return E1.OK;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 플라잉 시작
|
|
/// </summary>
|
|
/// <param name="fovInfo">FOV 정보</param>
|
|
/// <param name="param">추가 파라미터</param>
|
|
/// <returns>성공 유무</returns>
|
|
public override int StartFlying(FovInfo fovInfo, object param = null) {
|
|
if (!IsActivated || !IsFlyingEnabled()) {
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
try {
|
|
lock (LockThis) {
|
|
var sw = Stopwatch.StartNew();
|
|
MilEnvironment.ClearImage(_ParentImage);
|
|
sw.Stop();
|
|
LOG.I($"ClearImage {sw.ElapsedMilliseconds} msec");
|
|
|
|
sw.Restart();
|
|
StopLive();
|
|
sw.Stop();
|
|
LOG.I($"StopLive Process {sw.ElapsedMilliseconds} msec");
|
|
sw.Restart();
|
|
StopGrabMdigProcess();
|
|
sw.Stop();
|
|
LOG.I($"StopGrabMdigProcess Process {sw.ElapsedMilliseconds} msec");
|
|
sw.Restart();
|
|
StopFlyingMdigProcess();
|
|
sw.Stop();
|
|
LOG.I($"StopFlyingMdigProcess Process {sw.ElapsedMilliseconds} msec");
|
|
|
|
if (CamConfig.IsAlwaysSwTrigger()) {
|
|
SetSwTrigger();
|
|
}
|
|
else {
|
|
SetHwTrigger();
|
|
}
|
|
|
|
sw.Restart();
|
|
StartFlyingMdigProcess();
|
|
sw.Stop();
|
|
LOG.I($"StartFlyingMdigProcess {sw.ElapsedMilliseconds} msec");
|
|
|
|
SetFlyingStart(true);
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
return E1.OK;
|
|
}
|
|
|
|
private int StartFlyingMdigProcess() {
|
|
try {
|
|
lock (LockThis) {
|
|
_FlyingHookData.HookDigitizer = _Digitizer;
|
|
_FlyingHookData.HookImage = _OriginalImage;
|
|
_FlyingHookData.HookCnt = 0;
|
|
|
|
if (!_FlyingUserDataHandle.IsAllocated) {
|
|
_FlyingUserDataHandle = GCHandle.Alloc(_FlyingHookData);
|
|
}
|
|
|
|
if (_FlyingHookFuncPtr == null) {
|
|
_FlyingHookFuncPtr = new MIL_DIG_HOOK_FUNCTION_PTR(FlyingHookHandler);
|
|
}
|
|
|
|
if (_ProcImages != null) {
|
|
MIL.MdigProcess(
|
|
_Digitizer, Array.ConvertAll(_ProcImages, item => (MIL_ID)item), (MIL_INT)_ProcImages.Length, MIL.M_START, MIL.M_DEFAULT, _FlyingHookFuncPtr, GCHandle.ToIntPtr(_FlyingUserDataHandle));
|
|
}
|
|
|
|
// 원래 코드
|
|
//MIL.MdigProcess(_Digitizer, _FlyingChildImages, (MIL_INT)_FlyingChildImages.Length, MIL.M_START, MIL.M_DEFAULT, _FlyingHookFuncPtr, GCHandle.ToIntPtr(_FlyingUserDataHandle));
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
return E1.GENERIC;
|
|
}
|
|
|
|
return E1.OK;
|
|
}
|
|
|
|
private bool IsFlyingEnabled() {
|
|
return CamConfig.TriggerMode.IsFlying;
|
|
}
|
|
|
|
private bool IsFlyingStart() {
|
|
lock (LockThis) {
|
|
return IsActivated && IsFlyingEnabled() && _IsFlyingRunning;
|
|
}
|
|
}
|
|
|
|
private void SetFlyingStart(bool isFlyingStart) {
|
|
lock (LockThis) {
|
|
if (IsFlyingEnabled()) {
|
|
_IsFlyingRunning = isFlyingStart;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 호환되는 회색조 이미지 버퍼 가져오기
|
|
/// </summary>
|
|
/// <param name="imageSize">이미지 사이즈</param>
|
|
/// <param name="systemId">MIL 시스템 Id</param>
|
|
/// <returns>이미지 버퍼 MIL ID</returns>
|
|
public static MIL_ID GetCompatibleGrayImageBuffer(ImageSize imageSize, MIL_ID systemId) {
|
|
if (!MilEnvironment.Instance.HasValidLicense()) {
|
|
return MIL.M_NULL;
|
|
}
|
|
|
|
MIL_ID BufIdPtr = MIL.M_NULL;
|
|
MIL.MbufAlloc2d(systemId, imageSize.Width, imageSize.Height, 8, 60L, ref BufIdPtr);
|
|
MIL.MbufClear(BufIdPtr, 0.0);
|
|
|
|
return BufIdPtr;
|
|
}
|
|
|
|
private void SwTriggerOn() {
|
|
if (!IsActivated) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
if (CamConfig.CamConnConfig.BoardType == eBoardType.MIL_CXP_RAPIXO) {
|
|
//FlyingVision
|
|
MIL.MdigControl(_Digitizer, MIL.M_TIMER1 + MIL.M_TIMER_TRIGGER_SOFTWARE, 1);
|
|
}
|
|
else if (CamConfig.CamConnConfig.BoardType == eBoardType.MIL_GIGE) {
|
|
// GigE
|
|
MIL.MdigControl(_Digitizer, MIL.M_GRAB_TRIGGER_SOFTWARE, MIL.M_ACTIVATE);
|
|
}
|
|
else {
|
|
LOG.FuncE("Check Cam BoardType");
|
|
}
|
|
|
|
}
|
|
catch (Exception e) {
|
|
LOG.FuncE(e.Message);
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
private class HookDataStruct {
|
|
public MIL_ID HookDigitizer;
|
|
public MIL_ID HookImage;
|
|
public int HookCnt;
|
|
}
|
|
}
|
|
}
|
|
#endif |