using AI.Common; using AI.Common.Log; using AIDiagnosis.Common.Enums; using AIDiagnosis.Common.Models; using MyocardialSegmentLib; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Threading; using Vinno.AI.CommonSDK.Enums; using Vinno.AI.CommonSDK.Models; using Vinno.AI.CommonSDK.Tools; using Vinno.AI.MyocardialDiagnosisSDK.Enums; using Vinno.AI.MyocardialDiagnosisSDK.Interfaces; using Vinno.AI.MyocardialDiagnosisSDK.Models; using Vinno.AI.Service.Common.Interfaces; using Vinno.AI.Service.Common.Models; using Vinno.AI.Service.Common.Tools; using MyocardialDiagnosis = MyocardialDiagnosisSDK.MyocardialDiagnosis; namespace Vinno.AI.MyocardialDiagnosisService { public class MyocardialDiagnosisService : IMyocardialDiagnosisService, IDisposable, IEngine { private readonly string _modelFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Networks"); private readonly ConcurrentStack _singleImageCache; private PipeServer _singleImagePipeServer; private ImageProvider _imageProvider; private MyocardialDiagnosis _myocardialDiagnosis; private bool _disposed; public static List AllFunctions { get; } static MyocardialDiagnosisService() { AllFunctions = MyocardialDiagnosis.AllFunctions; } public static void Init(FunctionInfo enableFunction, FunctionInfo currentUsedFunction) { MyocardialDiagnosis.Init(enableFunction, currentUsedFunction); } public MyocardialDiagnosisService() { try { _singleImageCache = new ConcurrentStack(); _singleImagePipeServer = new PipeServer(AIDiagnosisSystemConsts.PipeForMyocardialDiagnosisSingleImage); _singleImagePipeServer.LogMsgThrow += OnLogMsgThrow; _singleImagePipeServer.DataReceived += OnDataReceived; _singleImagePipeServer.StartAndReceive(); _imageProvider = new ImageProvider(AIEnumType.MyocardialDiagnosis); } catch (Exception ex) { Logger.Error($"MyocardialDiagnosisService-Constructor error:{ex}"); } } public void Initialize(MyocardialDiagnosisParameter myocardialParameter, bool hasImageProvider) { try { CloseDiagnosis(); var cpuNumber = myocardialParameter.CPUNumber; var detectMode = (EnumDetectMode)myocardialParameter.DetectMode; var detectTps = myocardialParameter.DetectTps; var intervalTime = myocardialParameter.IntervalTime; var isCompleteMyocardialImg = myocardialParameter.CompleteMyocardialImg; switch (myocardialParameter.MyocardialDiagnosisType) { case AIEnumMyocardialDiagnosisType.HumanMyocardialDiagnosis: if (_myocardialDiagnosis == null) { _myocardialDiagnosis = new MyocardialDiagnosis(Setting.Instance.IsSaveDetectImage, Setting.Instance.IsSaveAllImage, Logger.LogDir, hasImageProvider ? _imageProvider : null, cpuNumber, _modelFolder, EnumMyocardialInferWorkName.HumanMyocardialSegment, detectMode, detectTps, intervalTime); _myocardialDiagnosis.CompleteMyocardialImg = isCompleteMyocardialImg; _myocardialDiagnosis.StartEvaluation += OnStartEvaluation; _myocardialDiagnosis.FinishEvaluation += OnFinishEvaluation; _myocardialDiagnosis.NotifyError += OnNotifyError; _myocardialDiagnosis.NotifyLog += OnNotifyLog; } break; case AIEnumMyocardialDiagnosisType.MiceMyocardialDiagnosis: if (_myocardialDiagnosis == null) { _myocardialDiagnosis = new MyocardialDiagnosis(Setting.Instance.IsSaveDetectImage, Setting.Instance.IsSaveAllImage, Logger.LogDir, hasImageProvider ? _imageProvider : null, cpuNumber, _modelFolder, EnumMyocardialInferWorkName.MiceMyocardialSegment, detectMode, detectTps, intervalTime); _myocardialDiagnosis.CompleteMyocardialImg = isCompleteMyocardialImg; _myocardialDiagnosis.StartEvaluation += OnStartEvaluation; _myocardialDiagnosis.FinishEvaluation += OnFinishEvaluation; _myocardialDiagnosis.NotifyError += OnNotifyError; _myocardialDiagnosis.NotifyLog += OnNotifyLog; } break; case AIEnumMyocardialDiagnosisType.RatMyocardialDiagnosis: if (_myocardialDiagnosis == null) { _myocardialDiagnosis = new MyocardialDiagnosis(Setting.Instance.IsSaveDetectImage, Setting.Instance.IsSaveAllImage, Logger.LogDir, hasImageProvider ? _imageProvider : null, cpuNumber, _modelFolder, EnumMyocardialInferWorkName.RatMyocardialSegment, detectMode, detectTps, intervalTime); _myocardialDiagnosis.CompleteMyocardialImg = isCompleteMyocardialImg; _myocardialDiagnosis.StartEvaluation += OnStartEvaluation; _myocardialDiagnosis.FinishEvaluation += OnFinishEvaluation; _myocardialDiagnosis.NotifyError += OnNotifyError; _myocardialDiagnosis.NotifyLog += OnNotifyLog; } break; } } catch (Exception ex) { Logger.Error($"MyocardialDiagnosisService-Initialize error:{ex}"); } } /// /// 切换引擎 /// /// public void SwitchEngines(FunctionInfo functionInfo) { try { MyocardialDiagnosis.SwitchAIEngines(functionInfo); if (_myocardialDiagnosis != null) { _myocardialDiagnosis.SwitchAIEngines2(functionInfo); } } catch (Exception ex) { Logger.Error($"MyocardialDiagnosisService-SwitchEngines error:{ex}"); } } public void Start() { try { if (_myocardialDiagnosis != null) { _myocardialDiagnosis.Start(); } } catch (Exception ex) { Logger.Error($"MyocardialDiagnosisService-Start error:{ex}"); } } public void Stop() { try { if (_myocardialDiagnosis != null) { _myocardialDiagnosis.Stop(); } } catch (Exception ex) { Logger.Error($"MyocardialDiagnosisService-Stop error:{ex}"); } } public void SetDetectTps(int detectTps) { try { if (_myocardialDiagnosis != null) { _myocardialDiagnosis.DetectTps = detectTps; } } catch (Exception ex) { Logger.Error($"MyocardialDiagnosisService-SetDetectTps error:{ex}"); } } public void SetIntervalTime(int intervalTime) { try { if (_myocardialDiagnosis != null) { _myocardialDiagnosis.IntervalTime = intervalTime; } } catch (Exception ex) { Logger.Error($"MyocardialDiagnosisService-SetIntervalTime error:{ex}"); } } public void SetDetectMode(AIEnumDetectMode detectMode) { try { if (_myocardialDiagnosis != null) { _myocardialDiagnosis.DetectMode = (EnumDetectMode)detectMode; } } catch (Exception ex) { Logger.Error($"MyocardialDiagnosisService-SetDetectMode error:{ex}"); } } public void SetIsCompleteMyocardialImg(bool isCompleteMyocardiaImg) { try { if (_myocardialDiagnosis != null) { _myocardialDiagnosis.CompleteMyocardialImg = isCompleteMyocardiaImg; } } catch (Exception ex) { Logger.Error($"MyocardialDiagnosisService-SetIsCompleteMyocardialImg error:{ex}"); } } public TransAIDetectedObject DetectOneByteImage(bool isCircle) { try { byte[] byteImage = null; int retryCount = 0; while (!_singleImageCache.TryPop(out byteImage) && retryCount < 50) { Thread.Sleep(10); retryCount++; } if (byteImage == null) { Logger.Error($"MyocardialDiagnosisService-DetectOneByteImage Get Image Cache Fail"); return null; } var detectedObject = _myocardialDiagnosis?.DetectOneImage(byteImage, isCircle); return AICommonServiceConvertHelper.ConvertDetectedObjectsToTransAIDetectedObject(detectedObject); } catch (Exception ex) { Logger.Error($"MyocardialDiagnosisService-DetectOneByteImage error:{ex}"); return null; } } public TransAIDetectedObject DetectOneRawImage(int height, int width, AIEnumColorType colorType, bool isCircle) { try { byte[] byteImage = null; int retryCount = 0; while (!_singleImageCache.TryPop(out byteImage) && retryCount < 50) { Thread.Sleep(10); retryCount++; } if (byteImage == null) { Logger.Error($"MyocardialDiagnosisService-DetectOneRawImage Get Image Cache Fail"); return null; } var rawImage = new RawImage(byteImage, width, height, (EnumColorType)colorType); var detectedObject = _myocardialDiagnosis?.DetectOneImage(rawImage, isCircle); return AICommonServiceConvertHelper.ConvertDetectedObjectsToTransAIDetectedObject(detectedObject); } catch (Exception ex) { Logger.Error($"MyocardialDiagnosisService-DetectOneRawImage error:{ex}"); return null; } } public bool AbleToBeCompleted(TransAIDetectedObject transAIDetectedObject) { try { if (_myocardialDiagnosis == null) { Logger.Error($"AbleToBeCompleted Error:Myocardial Diagnosis is null"); return false; } var detectedObject = AICommonServiceConvertHelper.ConvertTransAIDetectedObjectToDetectedObject(transAIDetectedObject); return _myocardialDiagnosis.AbleToBeCompleted(detectedObject); } catch (Exception ex) { Logger.Error($"MyocardialDiagnosisService-AbleToBeCompleted error:{ex}"); return false; } } public TransAIDetectedObject CompleteOneImage(TransAIDetectedObject transAIDetectedObject) { try { if (_myocardialDiagnosis == null) { Logger.Error($"Complete One Image Error:Myocardial Diagnosis is null"); return null; } var detectedObject = AICommonServiceConvertHelper.ConvertTransAIDetectedObjectToDetectedObject(transAIDetectedObject); var result = _myocardialDiagnosis?.CompleteOneImage(detectedObject); return AICommonServiceConvertHelper.ConvertDetectedObjectsToTransAIDetectedObject(result); } catch (Exception ex) { Logger.Error($"MyocardialDiagnosisService-CompleteOneImage error:{ex}"); return null; } } public TransAIDetectedObject ExtractContours(TransAIDetectedObject transAIDetectedObject) { try { if (_myocardialDiagnosis == null) { Logger.Error($"Extract Contours Error:Myocardial Diagnosis is null"); return null; } var detectedObject = AICommonServiceConvertHelper.ConvertTransAIDetectedObjectToDetectedObject(transAIDetectedObject); var result = _myocardialDiagnosis?.ExtractContours(detectedObject); return AICommonServiceConvertHelper.ConvertDetectedObjectsToTransAIDetectedObject(result); } catch (Exception ex) { Logger.Error($"MyocardialDiagnosisService- ExtractContours 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($"MyocardialDiagnosisService-SendRawImageData error:{ex}"); } } /// /// Send Byte Image Data For Pipe /// public void SendByteImageData() { try { _imageProvider?.ReceiveByteImageData(); } catch (Exception ex) { Logger.Error($"MyocardialDiagnosisService-SendByteImageData error:{ex}"); } } public TransAIDetectedObject ModifyEDESFrame(TransAIDetectedObject transAIDetectedObject, AIEnumMyocardialType type) { try { if (_myocardialDiagnosis == null) { Logger.Error($"ModifyEDESFrame Error:Myocardial Diagnosis is null"); return null; } var detectedObject = AICommonServiceConvertHelper.ConvertTransAIDetectedObjectToDetectedObject(transAIDetectedObject); var myocardialType = (EnumMyocardialType)type; var result = _myocardialDiagnosis?.ModifyEDESFrame(detectedObject, myocardialType); return AICommonServiceConvertHelper.ConvertDetectedObjectsToTransAIDetectedObject(result); } catch (Exception ex) { Logger.Error($"MyocardialDiagnosisService-ModifyEDESFrame error:{ex}"); return null; } } public void Close() { try { Logger.Info($"MyocardialDiagnosisService-Close Invoke"); CloseDiagnosis(); } catch (Exception ex) { Logger.Error($"MyocardialDiagnosisService-Close error:{ex}"); } } private void CloseDiagnosis() { if (_myocardialDiagnosis != null) { _myocardialDiagnosis.StartEvaluation -= OnStartEvaluation; _myocardialDiagnosis.FinishEvaluation -= OnFinishEvaluation; _myocardialDiagnosis.NotifyError -= OnNotifyError; _myocardialDiagnosis.NotifyLog -= OnNotifyLog; _myocardialDiagnosis.Close(); _myocardialDiagnosis = null; } } public void Dispose() { try { if (!_disposed) { Logger.Info($"MyocardialDiagnosisService-Start Dispose"); CloseDiagnosis(); if (_singleImagePipeServer != null) { _singleImagePipeServer.DataReceived -= OnDataReceived; _singleImagePipeServer.Dispose(); _singleImagePipeServer.LogMsgThrow -= OnLogMsgThrow; _singleImagePipeServer = null; } _imageProvider.Dispose(); _imageProvider = null; _disposed = true; Logger.Info($"MyocardialDiagnosisService Dispose End"); } } catch (Exception ex) { Logger.Error($"MyocardialDiagnosisService-Dispose error:{ex}"); } } private void OnStartEvaluation(object sender, EventArgs e) { NotificationSender.SendNotification(new AINotificationArgs() { NotificationType = AIEnumNotificationType.MyocardialDiagnosisStartEvaluationRaised, Params = e }); } private void OnFinishEvaluation(object sender, DetectedObject e) { var transDetectedObject = AICommonServiceConvertHelper.ConvertDetectedObjectsToTransAIDetectedObject(e); NotificationSender.SendNotification(new AINotificationArgs() { NotificationType = AIEnumNotificationType.MyocardialDiagnosisFinishEvaluationRaised, Params = transDetectedObject }); } private void OnNotifyLog(object sender, LogEventArgs e) { if (e == null) { return; } switch (e.LogType) { case EnumLogType.InfoLog: Logger.Info($"MyocardialDiagnosisService OnNotifyLog:{e.Msg}"); break; case EnumLogType.WarnLog: Logger.Warning($"MyocardialDiagnosisService OnNotifyLog:{e.Msg}"); break; case EnumLogType.ErrorLog: case EnumLogType.FatalLog: default: Logger.Error($"MyocardialDiagnosisService OnNotifyLog:{e.Msg}"); break; } var logEventArgs = AICommonServiceConvertHelper.ConvertLogEventArgsToAILogEventArgs(e); NotificationSender.SendNotification(new AINotificationArgs() { NotificationType = AIEnumNotificationType.MyocardialDiagnosisNotifyLogRaised, Params = logEventArgs }); } private void OnNotifyError(object sender, ErrorEventArgs e) { Logger.Error($"MyocardialDiagnosisService OnNotifyError:{e.GetException()}"); var logEventArgs = AICommonServiceConvertHelper.ConvertErrorEventArgsToAILogEventArgs(e); NotificationSender.SendNotification(new AINotificationArgs() { NotificationType = AIEnumNotificationType.MyocardialDiagnosisNotifyLogRaised, 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($"MyocardialDiagnosisService-OnDataReceived error:{ex}"); } } } }