using AI.Common; using AI.Common.Log; using AIDiagnosis.Common.Enums; using AIDiagnosis.Common.Models; using AutoEFCalculationLib; using AutoEFDiagnosisSDK.Enums; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using Vinno.AI.AutoEFDiagnosisSDK.Enums; using Vinno.AI.AutoEFDiagnosisSDK.Interfaces; using Vinno.AI.AutoEFDiagnosisSDK.Models; using Vinno.AI.AutoEFDiagnosisService.Tools; using Vinno.AI.CommonSDK.Enums; using Vinno.AI.CommonSDK.Models; using Vinno.AI.CommonSDK.Tools; using Vinno.AI.Service.Common.Interfaces; using Vinno.AI.Service.Common.Models; using Vinno.AI.Service.Common.Tools; using AutoEFDiagnosis = AutoEFDiagnosisSDK.AutoEFDiagnosis; namespace Vinno.AI.AutoEFDiagnosisService { public class AutoEFDiagnosisService : IAutoEFDiagnosisService, IDisposable, IEngine { private readonly string _modelFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Networks"); private readonly ConcurrentStack _singleImageCache; private PipeServer _singleImagePipeServer; private ImageProvider _imageProvider; private AutoEFDiagnosis _autoEFDiagnosis; private bool _disposed; public static List AllFunctions { get; } static AutoEFDiagnosisService() { AllFunctions = AutoEFDiagnosis.AllFunctions; } public static void Init(FunctionInfo enableFunction, FunctionInfo currentUsedFunction) { AutoEFDiagnosis.Init(enableFunction, currentUsedFunction); } public AutoEFDiagnosisService() { try { _singleImageCache = new ConcurrentStack(); _singleImagePipeServer = new PipeServer(AIDiagnosisSystemConsts.PipeForAutoEFDiagnosisSingleImage); _singleImagePipeServer.LogMsgThrow += OnLogMsgThrow; _singleImagePipeServer.DataReceived += OnDataReceived; _singleImagePipeServer.StartAndReceive(); _imageProvider = new ImageProvider(AIEnumType.AutoEFDiagnosis); } catch (Exception ex) { Logger.Error($"AutoEFDiagnosisService-Constructor error:{ex}"); } } /// /// 切换引擎 /// /// public void SwitchEngines(FunctionInfo functionInfo) { try { AutoEFDiagnosis.SwitchAIEngines(functionInfo); if (_autoEFDiagnosis != null) { _autoEFDiagnosis.SwitchAIEngines2(functionInfo); } } catch (Exception ex) { Logger.Error($"AutoEFDiagnosisService-SwitchEngines error:{ex}"); } } public void Initialize(AutoEFDiagnosisParameter autoEFDiagnosisParameter, bool hasImageProvider) { try { CloseDiagnosis(); var cpuNumber = autoEFDiagnosisParameter.CPUNumber; var layerCount = autoEFDiagnosisParameter.LayerCount; var edcontrolLayersCount = autoEFDiagnosisParameter.EdcontrolLayersCount; var escontrolLayersCount = autoEFDiagnosisParameter.EscontrolLayersCount; var isReturnEveryImgResult = autoEFDiagnosisParameter.IsReturnEveryImgResult; var detectMode = (EnumDetectMode)autoEFDiagnosisParameter.DetectMode; var detectTps = autoEFDiagnosisParameter.DetectTps; var intervalTime = autoEFDiagnosisParameter.IntervalTime; var cmPerPixel = autoEFDiagnosisParameter.CmPerPixel; var reprocess = (EnumReprocess)autoEFDiagnosisParameter.Reprocess; EnumAutoEFDiagnosisType diagnosisType = autoEFDiagnosisParameter.AutoEFDiagnosisType == AIEnumAutoEFDiagnosisType.HumanAutoEFDiagnosis ? EnumAutoEFDiagnosisType.HumanAutoEFDiagnosis : EnumAutoEFDiagnosisType.VetAutoEFDiagnosis; _autoEFDiagnosis = new AutoEFDiagnosis(cpuNumber, _modelFolder, Setting.Instance.IsSaveDetectImage, Setting.Instance.IsSaveAllImage, Logger.LogDir, layerCount, escontrolLayersCount, edcontrolLayersCount, isReturnEveryImgResult, diagnosisType, hasImageProvider ? _imageProvider : null, cmPerPixel, detectMode, detectTps, intervalTime, reprocess); _autoEFDiagnosis.StartEvaluation += OnStartEvaluation; _autoEFDiagnosis.FinishEvaluation += OnFinishEvaluation; _autoEFDiagnosis.NotifyError += OnNotifyError; _autoEFDiagnosis.NotifyLog += OnNotifyLog; } catch (Exception ex) { Logger.Error($"AutoEFDiagnosisService-Initialize error:{ex}"); } } /// /// 启用AutoEF /// /// 整个视频帧数 /// 探头中像素与实际单位转换的参数 public void StartAutotEFCalculation(long totalFrameCount, double cmPerPixel, AIEnumReprocess reprocess) { try { if (_autoEFDiagnosis == null) { Logger.Error($"StartAutotEF Error:AutoEF Diagnosis is null"); return; } EnumReprocess enumReprocess = (EnumReprocess)reprocess; _autoEFDiagnosis.StartAutotEFCalculation(totalFrameCount, cmPerPixel, enumReprocess); } catch (Exception ex) { Logger.Error($"AutoEFDiagnosisService-StartAutotEFCalculation error:{ex}"); } } /// /// 推入一张裸图并返回AutoEF结果 /// /// /// public void DetectOneRawImageForAutoEFCalculation(int height, int width, AIEnumColorType colorType, double frameTime) { try { byte[] byteImage = null; int retryCount = 0; while (!_singleImageCache.TryPop(out byteImage) && retryCount < 50) { Thread.Sleep(10); retryCount++; } if (byteImage == null) { Logger.Error($"AutoEFDiagnosisService-DetectOneRawImageForAutoEFCalculation Get Image Cache Fail"); return; } var rawImage = new RawImage(byteImage, width, height, (EnumColorType)colorType); _autoEFDiagnosis.DetectOneImageAsync(rawImage, frameTime); } catch (Exception ex) { Logger.Error($"AutoEFDiagnosisService-DetectOneRawImageForAutoEFCalculation error:{ex}"); } } /// /// 推入一张图并返回AutoEF结果 /// /// /// /// public void DetectOneByteImageForAutoEFCalculation(double frameTime) { try { byte[] byteImage = null; int retryCount = 0; while (!_singleImageCache.TryPop(out byteImage) && retryCount < 50) { Thread.Sleep(10); retryCount++; } if (byteImage == null) { Logger.Error($"AutoEFDiagnosisService-DetectOneByteImageForAutoEFCalculation Get Image Cache Fail"); return; } _autoEFDiagnosis.DetectOneImageAsync(byteImage, frameTime); } catch (Exception ex) { Logger.Error($"AutoEFDiagnosisService-DetectOneByteImageForAutoEFCalculation error:{ex}"); } } /// /// 停止AutoEF并返回结果,若IsReturnEveryImgResult为True,则返回所有帧的AutoEF结果,若IsReturnEveryImgResult为False,则只返回ES,ED两张图的结果 /// /// public Dictionary StopAutoEFCalculation() { try { var result = _autoEFDiagnosis.StopAutotEFCalculation(); if (result == null) { return null; } else { Dictionary dict = new Dictionary(); foreach (var key in result.Keys.ToArray()) { var aiEDESDetectResult = AIConvertHelper.ConvertEDESDetectResultToAIEDESDetectResult(result[key]); dict.Add(key, aiEDESDetectResult); } return dict; } } catch (Exception ex) { Logger.Error($"AutoEFDiagnosisService-StopAutoEFCalculation error:{ex}"); return null; } } public void Start() { try { if (_autoEFDiagnosis != null) { _autoEFDiagnosis.Start(); } } catch (Exception ex) { Logger.Error($"AutoEFDiagnosisService-Start error:{ex}"); } } public void Stop() { try { if (_autoEFDiagnosis != null) { _autoEFDiagnosis.Stop(); } } catch (Exception ex) { Logger.Error($"AutoEFDiagnosisService-Stop error:{ex}"); } } public void SetDetectTps(int detectTps) { try { if (_autoEFDiagnosis != null) { _autoEFDiagnosis.DetectTps = detectTps; } } catch (Exception ex) { Logger.Error($"AutoEFDiagnosisService-SetDetectTps error:{ex}"); } } public void SetIntervalTime(int intervalTime) { try { if (_autoEFDiagnosis != null) { _autoEFDiagnosis.IntervalTime = intervalTime; } } catch (Exception ex) { Logger.Error($"AutoEFDiagnosisService-SetIntervalTime error:{ex}"); } } public void SetDetectMode(AIEnumDetectMode detectMode) { try { if (_autoEFDiagnosis != null) { _autoEFDiagnosis.DetectMode = (EnumDetectMode)detectMode; } } catch (Exception ex) { Logger.Error($"AutoEFDiagnosisService-SetDetectMode error:{ex}"); } } /// /// 设置一个像素代表的实际物理距离是多少cm /// /// public void SetCmPerPixel(double cmPerPixel) { try { if (_autoEFDiagnosis != null) { _autoEFDiagnosis.CmPerPixel = cmPerPixel; } } catch (Exception ex) { Logger.Error($"AutoEFDiagnosisService-SetCmPerPixel error:{ex}"); } } /// /// 设置后处理方式(仅人用支持) /// /// public void SetReprocess(AIEnumReprocess reprocess) { try { if (_autoEFDiagnosis != null) { _autoEFDiagnosis.Reprocess = (EnumReprocess)reprocess; } } catch (Exception ex) { Logger.Error($"AutoEFDiagnosisService-SetReprocess error:{ex}"); } } /// /// 检测单张Byte Image /// /// 图像上一个像素实际代表的物理距离是多少cm /// public AILVVolumeCalcResult DetectOneByteImage(double cmPerPixel, AIEnumReprocess reprocess) { try { byte[] byteImage = null; int retryCount = 0; while (!_singleImageCache.TryPop(out byteImage) && retryCount < 50) { Thread.Sleep(10); retryCount++; } if (byteImage == null) { Logger.Error($"AutoEFDiagnosisService-DetectOneByteImage Get Image Cache Fail"); return null; } var autoDFRCalcResult = _autoEFDiagnosis.DetectOneImage(byteImage, cmPerPixel, (EnumReprocess)reprocess); return AIConvertHelper.ConvertLVVolumeCalcResultToAILVVolumeCalcResult(autoDFRCalcResult); } catch (Exception ex) { Logger.Error($"AutoEFDiagnosisService-DetectOneByteImage error:{ex}"); return null; } } public AILVVolumeCalcResult DetectOneRawImage(int height, int width, AIEnumColorType colorType, double cmPerPixel, AIEnumReprocess reprocess) { try { byte[] byteImage = null; int retryCount = 0; while (!_singleImageCache.TryPop(out byteImage) && retryCount < 50) { Thread.Sleep(10); retryCount++; } if (byteImage == null) { Logger.Error($"AutoEFDiagnosisService-DetectOneRawImage Get Image Cache Fail"); return null; } var rawImage = new RawImage(byteImage, width, height, (EnumColorType)colorType); var autoDFRCalcResult = _autoEFDiagnosis.DetectOneImage(rawImage, cmPerPixel, (EnumReprocess)reprocess); return AIConvertHelper.ConvertLVVolumeCalcResultToAILVVolumeCalcResult(autoDFRCalcResult); } catch (Exception ex) { Logger.Error($"AutoEFDiagnosisService-DetectOneRawImage error:{ex}"); return null; } } public Dictionary GetEDESFrameResult(Dictionary allImageResults) { try { if (allImageResults == null) { Logger.Error($"AutoEFDiagnosisService-GetEDESFrameResult error:allImageResults is null"); return null; } if (allImageResults.Count == 0) { Logger.Error($"AutoEFDiagnosisService-GetEDESFrameResult error:allImageResults is empty"); return null; } Dictionary imageResults = new Dictionary(); foreach (var key in allImageResults.Keys.ToArray()) { var result = AIConvertHelper.ConvertAILVVolumeCalcResultToLVVolumeCalcResult(allImageResults[key]); imageResults.Add(key, result); } var edesResults = _autoEFDiagnosis.GetEDESFrameResult(imageResults); Dictionary aiEDESResults; if (edesResults == null) { aiEDESResults = null; } else { aiEDESResults = new Dictionary(); foreach (var key in edesResults.Keys.ToArray()) { var aiEDESResult = AIConvertHelper.ConvertEDESDetectResultToAIEDESDetectResult(edesResults[key]); aiEDESResults.Add(key, aiEDESResult); } } return aiEDESResults; } catch (Exception ex) { Logger.Error($"AutoEFDiagnosisService-GetEDESFrameResult error:{ex}"); return null; } } /// /// Send Raw Image Data For Pipe /// /// /// /// public void SendRawImageData(int height, int width, AIEnumColorType colorType) { try { _imageProvider?.ReceiveRawImageData(height, width, (EnumColorType)colorType); } catch (Exception ex) { Logger.Error($"AutoEFDiagnosisService-SendRawImageData error:{ex}"); } } /// /// Send Byte Image Data For Pipe /// public void SendByteImageData() { try { _imageProvider?.ReceiveByteImageData(); } catch (Exception ex) { Logger.Error($"AutoEFDiagnosisService-SendByteImageData error:{ex}"); } } public void Close() { try { Logger.Info($"AutoEFDiagnosisService-Close Invoke"); CloseDiagnosis(); } catch (Exception ex) { Logger.Error($"AutoEFDiagnosisService-Close error:{ex}"); } } private void CloseDiagnosis() { if (_autoEFDiagnosis != null) { _autoEFDiagnosis.StartEvaluation -= OnStartEvaluation; _autoEFDiagnosis.FinishEvaluation -= OnFinishEvaluation; _autoEFDiagnosis.NotifyError -= OnNotifyError; _autoEFDiagnosis.NotifyLog -= OnNotifyLog; _autoEFDiagnosis.Close(); _autoEFDiagnosis = null; } } public void Dispose() { try { if (!_disposed) { Logger.Info($"AutoEFDiagnosisService-Start Dispose"); CloseDiagnosis(); if (_singleImagePipeServer != null) { _singleImagePipeServer.DataReceived -= OnDataReceived; _singleImagePipeServer.Dispose(); _singleImagePipeServer.LogMsgThrow -= OnLogMsgThrow; _singleImagePipeServer = null; } _disposed = true; Logger.Info($"AutoEFDiagnosisService Dispose End"); } } catch (Exception ex) { Logger.Error($"AutoEFDiagnosisService-Dispose error:{ex}"); } } private void OnStartEvaluation(object sender, EventArgs e) { NotificationSender.SendNotification(new AINotificationArgs() { NotificationType = AIEnumNotificationType.AutoEFDiagnosisStartEvaluationRaised }); } private void OnFinishEvaluation(object sender, LVVolumeCalcResult e) { var aiLVVolumeCalcResult = AIConvertHelper.ConvertLVVolumeCalcResultToAILVVolumeCalcResult(e); NotificationSender.SendNotification(new AINotificationArgs() { NotificationType = AIEnumNotificationType.AutoEFDiagnosisFinishEvaluationRaised, Params = aiLVVolumeCalcResult }); } private void OnNotifyLog(object sender, LogEventArgs e) { if (e == null) { return; } switch (e.LogType) { case EnumLogType.InfoLog: Logger.Info($"AutoEFDiagnosisService OnNotifyLog:{e.Msg}"); break; case EnumLogType.WarnLog: Logger.Warning($"AutoEFDiagnosisService OnNotifyLog:{e.Msg}"); break; case EnumLogType.ErrorLog: case EnumLogType.FatalLog: default: Logger.Error($"AutoEFDiagnosisService OnNotifyLog:{e.Msg}"); break; } var logEventArgs = AICommonServiceConvertHelper.ConvertLogEventArgsToAILogEventArgs(e); NotificationSender.SendNotification(new AINotificationArgs() { NotificationType = AIEnumNotificationType.AutoEFDiagnosisNotifyLogRaised, Params = logEventArgs }); } private void OnNotifyError(object sender, ErrorEventArgs e) { Logger.Error($"AutoEFDiagnosisService OnNotifyError:{e.GetException()}"); var logEventArgs = AICommonServiceConvertHelper.ConvertErrorEventArgsToAILogEventArgs(e); NotificationSender.SendNotification(new AINotificationArgs() { NotificationType = AIEnumNotificationType.AutoEFDiagnosisNotifyLogRaised, Params = logEventArgs }); } private void OnLogMsgThrow(object sender, AILogEventArgs e) { if (e == null) { return; } switch (e.LogType) { case AIEnumLogType.ErrorLog: case AIEnumLogType.FatalLog: Logger.Error(e.Msg); break; case AIEnumLogType.WarnLog: Logger.Warning(e.Msg); break; case AIEnumLogType.InfoLog: default: Logger.Info(e.Msg); break; } } private void OnDataReceived(object sender, byte[] e) { try { _singleImageCache.Push(e); } catch (Exception ex) { Logger.Error($"AutoEFDiagnosisService-OnDataReceived error:{ex}"); } } } }