using System; using System.Reflection; using System.Text.Json; using Vinno.AI.CommonSDK.Enums; using Vinno.AI.CommonSDK.Interfaces; 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; namespace Vinno.AI.MyocardialDiagnosisSDK { public class MyocardialDiagnosis : IMyocardialDiagnosis { private readonly IMyocardialDiagnosisService _myocardialDiagnosisService; private IAIImageProvider _imageProvider; private bool _initialized; private bool _disposed; /// /// Used For Detect One Image /// private PipeClient _singleImagePipeClient; /// /// Used For Provide Raw Image /// private PipeClient _rawImageProviderPipeClient; /// /// Used For Provide Byte Image /// private PipeClient _byteImageProviderPipeClient; /// /// Raised when the image evaluation is started. /// public event EventHandler StartEvaluationNotification; /// /// Raised when the image evaluation is finished. /// public event EventHandler FinishEvaluationNotification; public MyocardialDiagnosis() { _myocardialDiagnosisService = AIManager.Instance.AIDiagnosisSystemJsonRpcClientManager?.GetService(); if (AIManager.Instance.AINotificationManager != null) { AIManager.Instance.AINotificationManager.NotificationReceived += OnNotificationReceived; } _singleImagePipeClient = new PipeClient(AIDiagnosisSystemConsts.PipeForMyocardialDiagnosisSingleImage); _singleImagePipeClient.LogMsgThrow += OnLogMsgThrow; _singleImagePipeClient.Start(); _rawImageProviderPipeClient = new PipeClient(AIDiagnosisSystemConsts.PipeForMyocardialDiagnosisRawImageProvider); _rawImageProviderPipeClient.LogMsgThrow += OnLogMsgThrow; _rawImageProviderPipeClient.Start(); _byteImageProviderPipeClient = new PipeClient(AIDiagnosisSystemConsts.PipeForMyocardialDiagnosisByteImageProvider); _byteImageProviderPipeClient.LogMsgThrow += OnLogMsgThrow; _byteImageProviderPipeClient.Start(); } /// /// 初始化Myocardial Diagnosis /// /// Myocardial Parameter /// Image Provider public void Initialize(MyocardialDiagnosisParameter myocardialParameter, IAIImageProvider imageProvider = null) { try { if (!_initialized) { _imageProvider = imageProvider; _myocardialDiagnosisService.Initialize(myocardialParameter, _imageProvider != null); _initialized = true; } } catch (Exception ex) { AIManager.Instance.AILogManager?.WriteLogInfo(new AILogEventArgs(AIEnumLogType.ErrorLog, $"错误方法名:{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}, 错误信息:{ex}")); } } /// /// Start Image Provider /// public void Start() { if (_imageProvider != null) { _myocardialDiagnosisService.Start(); _imageProvider.ByteImageProvided += OnByteImageProvided; _imageProvider.RawImageProvided += OnRawImageProvided; _imageProvider.Start(); } } /// /// Stop Image Provider /// public void Stop() { if (_imageProvider != null) { _imageProvider.ByteImageProvided -= OnByteImageProvided; _imageProvider.RawImageProvided -= OnRawImageProvided; _imageProvider.Stop(); } _myocardialDiagnosisService.Stop(); } private void OnLogMsgThrow(object sender, AILogEventArgs e) { AIManager.Instance.AILogManager?.WriteLogInfo(e); } private void OnNotificationReceived(object sender, AINotificationArgs e) { switch (e.NotificationType) { case AIEnumNotificationType.MyocardialDiagnosisStartEvaluationRaised: StartEvaluationNotification?.Invoke(this, EventArgs.Empty); break; case AIEnumNotificationType.MyocardialDiagnosisFinishEvaluationRaised: var transAIDetectedObject = JsonSerializer.Deserialize(e.Params?.ToString()); var detectedObject = AICommonConvertHelper.ConvertTransAIDetectedObjectToAIDetectedObject(transAIDetectedObject); FinishEvaluationNotification?.Invoke(this, detectedObject); break; case AIEnumNotificationType.MyocardialDiagnosisNotifyLogRaised: var logEventArgs = JsonSerializer.Deserialize(e.Params?.ToString()); AIManager.Instance.AILogManager?.WriteLogInfo(logEventArgs); break; } } /// /// 设置每秒图片吞吐量 /// /// 每秒图片吞吐量,必须大于0 public void SetDetectTps(int detectTps) { if (detectTps <= 0) { throw new ArgumentOutOfRangeException($"DetectTps Must > 0. DetectTps : {detectTps}"); } try { _myocardialDiagnosisService.SetDetectTps(detectTps); } catch (Exception ex) { AIManager.Instance.AILogManager?.WriteLogInfo(new AILogEventArgs(AIEnumLogType.ErrorLog, $"错误方法名:{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}, 错误信息:{ex}")); } } /// /// 设置间隔时间 /// /// public void SetIntervalTime(int intervalTime) { try { _myocardialDiagnosisService.SetIntervalTime(intervalTime); } catch (Exception ex) { AIManager.Instance.AILogManager?.WriteLogInfo(new AILogEventArgs(AIEnumLogType.ErrorLog, $"错误方法名:{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}, 错误信息:{ex}")); } } /// /// 设置检测模式 /// /// public void SetDetectMode(AIEnumDetectMode detectMode) { try { _myocardialDiagnosisService.SetDetectMode(detectMode); } catch (Exception ex) { AIManager.Instance.AILogManager?.WriteLogInfo(new AILogEventArgs(AIEnumLogType.ErrorLog, $"错误方法名:{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}, 错误信息:{ex}")); } } /// /// 设置是否对心肌圆形轮廓进行补全 /// /// public void SetIsCompleteMyocardialImg(bool isCompleteMyocardiaImg) { try { _myocardialDiagnosisService.SetIsCompleteMyocardialImg(isCompleteMyocardiaImg); } catch (Exception ex) { AIManager.Instance.AILogManager?.WriteLogInfo(new AILogEventArgs(AIEnumLogType.ErrorLog, $"错误方法名:{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}, 错误信息:{ex}")); } } /// /// 检测单张Raw Image /// /// 图像资源 /// 是否是基底类图片 /// public AIDetectedObject DetectOneImage(AIRawImage rawImage, bool isCircle) { if (rawImage == null) { throw new ArgumentNullException(nameof(rawImage)); } try { _singleImagePipeClient.SendBytes(rawImage.DataBuffer); var result = _myocardialDiagnosisService.DetectOneRawImage(rawImage.Height, rawImage.Width, rawImage.ColorType, isCircle); return AICommonConvertHelper.ConvertTransAIDetectedObjectToAIDetectedObject(result); } catch (Exception ex) { AIManager.Instance.AILogManager?.WriteLogInfo(new AILogEventArgs(AIEnumLogType.ErrorLog, $"错误方法名:{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}, 错误信息:{ex}")); return null; } } /// /// 检测单张Byte Image /// /// 图像资源 /// 是否是基底类图片 /// public AIDetectedObject DetectOneImage(byte[] byteImage, bool isCircle) { if (byteImage == null) { throw new ArgumentNullException(nameof(byteImage)); } try { _singleImagePipeClient.SendBytes(byteImage); var result = _myocardialDiagnosisService.DetectOneByteImage(isCircle); return AICommonConvertHelper.ConvertTransAIDetectedObjectToAIDetectedObject(result); } catch (Exception ex) { AIManager.Instance.AILogManager?.WriteLogInfo(new AILogEventArgs(AIEnumLogType.ErrorLog, $"错误方法名:{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}, 错误信息:{ex}")); return null; } } /// /// 检测出心肌轮廓后,判断单帧图的心肌轮廓是否能够补全成完整圆 /// /// 心肌检测结果 /// public bool AbleToBeCompleted(AIDetectedObject inferResult) { if (inferResult == null) { throw new ArgumentNullException(nameof(inferResult)); } try { var transAIDetectedObject = AICommonConvertHelper.ConvertAIDetectedObjectToTransAIDetectedObject(inferResult); return _myocardialDiagnosisService.AbleToBeCompleted(transAIDetectedObject); } catch (Exception ex) { AIManager.Instance.AILogManager?.WriteLogInfo(new AILogEventArgs(AIEnumLogType.ErrorLog, $"错误方法名:{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}, 错误信息:{ex}")); return false; } } /// /// 检测心肌图片,给出补全完整的心肌轮廓。 /// /// 心肌轮廓检测结果,是DetectOneImage方法得出的不补全的检测结果 /// public AIDetectedObject CompleteOneImage(AIDetectedObject segResult) { if (segResult == null) { throw new ArgumentNullException(nameof(segResult)); } try { var transAIDetectedObject = AICommonConvertHelper.ConvertAIDetectedObjectToTransAIDetectedObject(segResult); var result = _myocardialDiagnosisService.CompleteOneImage(transAIDetectedObject); return AICommonConvertHelper.ConvertTransAIDetectedObjectToAIDetectedObject(result); } catch (Exception ex) { AIManager.Instance.AILogManager?.WriteLogInfo(new AILogEventArgs(AIEnumLogType.ErrorLog, $"错误方法名:{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}, 错误信息:{ex}")); return null; } } /// /// 根据分割结果,提取相应内外轮廓的值 /// /// 心肌轮廓检测结果 /// public AIDetectedObject ExtractContours(AIDetectedObject segResult) { if (segResult == null) { throw new ArgumentNullException(nameof(segResult)); } try { var transAIDetectedObject = AICommonConvertHelper.ConvertAIDetectedObjectToTransAIDetectedObject(segResult); var result = _myocardialDiagnosisService.ExtractContours(transAIDetectedObject); return AICommonConvertHelper.ConvertTransAIDetectedObjectToAIDetectedObject(result); } catch (Exception ex) { AIManager.Instance.AILogManager?.WriteLogInfo(new AILogEventArgs(AIEnumLogType.ErrorLog, $"错误方法名:{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}, 错误信息:{ex}")); return null; } } /// /// 对心肌的EDES帧的内外轮廓做后处理,当前仅供人的心肌使用 /// /// 分割结果,使用其中的轮廓点 /// 输入的心肌切面的类型 /// 最终的图像内外轮廓经过后处理的结果,比原始分割的心肌轮廓更接近真实轮廓,0表示外轮廓、1表示内轮廓 public AIDetectedObject ModifyEDESFrame(AIDetectedObject segResult, AIEnumMyocardialType type) { if (segResult == null) { throw new ArgumentNullException(nameof(segResult)); } try { var transAIDetectedObject = AICommonConvertHelper.ConvertAIDetectedObjectToTransAIDetectedObject(segResult); var result = _myocardialDiagnosisService.ModifyEDESFrame(transAIDetectedObject, type); return AICommonConvertHelper.ConvertTransAIDetectedObjectToAIDetectedObject(result); } catch (Exception ex) { AIManager.Instance.AILogManager?.WriteLogInfo(new AILogEventArgs(AIEnumLogType.ErrorLog, $"错误方法名:{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}, 错误信息:{ex}")); return null; } } private void OnByteImageProvided(object sender, byte[] byteImage) { try { if (byteImage == null) { return; } _byteImageProviderPipeClient?.SendBytes(byteImage); _myocardialDiagnosisService.SendByteImageData(); } catch (Exception ex) { AIManager.Instance.AILogManager?.WriteLogInfo(new AILogEventArgs(AIEnumLogType.ErrorLog, $"错误方法名:{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}, 错误信息:{ex}")); } } private void OnRawImageProvided(object sender, AIRawImage rawImage) { try { if (rawImage == null) { return; } _rawImageProviderPipeClient?.SendBytes(rawImage.DataBuffer); _myocardialDiagnosisService.SendRawImageData(rawImage.Height, rawImage.Width, rawImage.ColorType); } catch (Exception ex) { AIManager.Instance.AILogManager?.WriteLogInfo(new AILogEventArgs(AIEnumLogType.ErrorLog, $"错误方法名:{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}, 错误信息:{ex}")); } } /// /// Close Myocardial Diagnosis /// public void Close() { try { if (_disposed) { return; } _initialized = false; if (_imageProvider != null) { _imageProvider.ByteImageProvided -= OnByteImageProvided; _imageProvider.RawImageProvided -= OnRawImageProvided; _imageProvider.Stop(); _imageProvider = null; } _myocardialDiagnosisService.Close(); } catch (Exception ex) { AIManager.Instance.AILogManager?.WriteLogInfo(new AILogEventArgs(AIEnumLogType.ErrorLog, $"错误方法名:{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}, 错误信息:{ex}")); } } public void Dispose() { try { if (!_disposed) { _initialized = false; if (AIManager.Instance.AINotificationManager != null) { AIManager.Instance.AINotificationManager.NotificationReceived -= OnNotificationReceived; } if (_imageProvider != null) { _imageProvider.ByteImageProvided -= OnByteImageProvided; _imageProvider.RawImageProvided -= OnRawImageProvided; _imageProvider.Stop(); _imageProvider = null; } if (_singleImagePipeClient != null) { _singleImagePipeClient.Dispose(); _singleImagePipeClient.LogMsgThrow -= OnLogMsgThrow; _singleImagePipeClient = null; } if (_rawImageProviderPipeClient != null) { _rawImageProviderPipeClient.Dispose(); _rawImageProviderPipeClient.LogMsgThrow -= OnLogMsgThrow; _rawImageProviderPipeClient = null; } if (_byteImageProviderPipeClient != null) { _byteImageProviderPipeClient.Dispose(); _byteImageProviderPipeClient.LogMsgThrow -= OnLogMsgThrow; _byteImageProviderPipeClient = null; } _disposed = true; } } catch (Exception ex) { AIManager.Instance.AILogManager?.WriteLogInfo(new AILogEventArgs(AIEnumLogType.ErrorLog, $"错误方法名:{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}, 错误信息:{ex}")); } } } }