123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539 |
- using AI.Common.Interface;
- using AI.Vet.Modules.VetHeartEndDiastoleEndSystole;
- using AI.Vet.Modules.VetHeartEPSS;
- using AI.Vet.Modules.VetHeartLVStudy;
- using AIDiagnosis.Common.Enums;
- using AIDiagnosis.Common.Helpers;
- using AIDiagnosis.Common.Interfaces;
- using AIDiagnosis.Common.Models;
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Reflection;
- using System.Threading;
- using System.Threading.Tasks;
- using VetHeartDiagnosisSDK.Enums;
- namespace VetHeartDiagnosisSDK
- {
- public class VetHeartDiagnosis
- {
- private const string _vendor = "Vinno";
- private static readonly List<string> _relatedDllList = new List<string>()
- {
- "AI.Vet.Modules.VetHeartEndDiastoleEndSystole.dll",
- "AI.Vet.Modules.VetHeartEPSS.dll",
- "AI.Vet.Modules.VetHeartLVStudy.dll",
- "AI.Vet.InferNets.VetHeartLargerStructureSeg.dll",
- "AI.Vet.InferNets.VetHeartMModeLargerStructureSeg.dll",
- "AI.Vet.InferNets.VetHeartMModeSmallerStructureSeg.dll",
- "AI.Vet.InferNets.VetHeartSmallerStructureSeg.dll",
- "AI.Vet.Tasks.VetHeartBModeCalculation.dll",
- "AI.Vet.Tasks.VetHeartBModeEPSSCalculation.dll",
- "AI.Vet.Tasks.VetHeartBModeLVStudyCalculation.dll",
- "AI.Vet.Tasks.VetHeartEndDiastoleEndSystoleRecognition.dll",
- "AI.Vet.Tasks.VetHeartImageTypeSection.dll",
- "AI.Vet.Tasks.VetHeartLargerStructureContourSegmentation.dll",
- "AI.Vet.Tasks.VetHeartMModeEPSSCalculation.dll",
- "AI.Vet.Tasks.VetHeartMModeLargerStructureContourSegmentation.dll",
- "AI.Vet.Tasks.VetHeartMModeLVStudyCalculation.dll",
- "AI.Vet.Tasks.VetHeartMModeSmallerStructureContourSegmentation.dll",
- "AI.Vet.Tasks.VetHeartSmallerStructureContourSegmentation.dll",
- "AI.Vet.Tasks.VetHeartStandardSectionRecognition.dll",
- "VetHeartStructurePostProcess.dll",
- "Networks\\AI.Vet.InferNets.VetHeart.LargerStructureSeg.emd",
- "Networks\\AI.Vet.InferNets.VetHeart.MModeLargerStructureSeg2.emd",
- "Networks\\AI.Vet.InferNets.VetHeart.MModeSmallerStructureSeg1.emd",
- "Networks\\AI.Vet.InferNets.VetHeart.SmallerStructureSeg.emd"
- };
- private readonly static Dictionary<EnumVetHeartDiagnosisEngineType, string> _aiDllDict = new Dictionary<EnumVetHeartDiagnosisEngineType, string>
- {
- { EnumVetHeartDiagnosisEngineType.VetHeartLVStudy, "AI.Vet.Modules.VetHeartLVStudy.dll" },
- { EnumVetHeartDiagnosisEngineType.VetHeartEPSS, "AI.Vet.Modules.VetHeartEPSS.dll" },
- { EnumVetHeartDiagnosisEngineType.VetHeartEndDiastoleEndSystole, "AI.Vet.Modules.VetHeartEndDiastoleEndSystole.dll" },
- };
- private static Dictionary<EnumVetHeartDiagnosisEngineType, string> _aiVersionDict = new Dictionary<EnumVetHeartDiagnosisEngineType, string>();
- private Dictionary<EnumVetHeartDiagnosisEngineType, IModule> _moduleDict = new Dictionary<EnumVetHeartDiagnosisEngineType, IModule>();
- private IImageProviderV2 _usImageProvider;
- private Dictionary<EnumVetHeartDiagnosisEngineType, string> _processIdDict = new Dictionary<EnumVetHeartDiagnosisEngineType, string>();
- private readonly ManualResetEvent _handlingImageEvent = new ManualResetEvent(true);
- private readonly object _detectObject = new object();
- private static string _aiType => EnumVetHeartDiagnosisFunction.VetHeartDiagnosis.ToString();
- /// <summary>
- /// 所有可用的功能列表
- /// </summary>
- private static FunctionInfo _enabledFunction;
- /// <summary>
- /// 当前正在使用的功能列表
- /// </summary>
- private static FunctionInfo _currentUsedFunction;
- private EnumDetectMode _detectmode;
- /// <summary>
- /// 图片计数
- /// </summary>
- private int _imageCounter;
- /// <summary>
- /// 帧率
- /// </summary>
- private int _displayFps = -1;
- /// <summary>
- /// 每隔多少帧检测一次
- /// </summary>
- private int _detectInterval;
- /// <summary>
- /// 计时用
- /// </summary>
- private int _startTickCount = -1;
- /// <summary>
- /// 所有功能列表
- /// </summary>
- public static List<FunctionInfo> AllFunctions { get; }
- /// <summary>
- /// Raised when the image evaluation is started.
- /// </summary>
- public event EventHandler StartEvaluation;
- /// <summary>
- /// Raised when the image evaluation is finished.
- /// </summary>
- public event EventHandler<IReadOnlyDictionary<IDataId, IReadOnlyList<IResultData>>> FinishEvaluation;
- /// <summary>
- /// Raised when event NotifyLog raised from AI diag system
- /// </summary>
- public event EventHandler<LogEventArgs> NotifyLog;
- /// <summary>
- /// 检测模式
- /// </summary>
- public EnumDetectMode DetectMode
- {
- get
- {
- return _detectmode;
- }
- set
- {
- if (_detectmode != value)
- {
- _detectmode = value;
- ResetParameters();
- }
- }
- }
- /// <summary>
- /// 每秒检测次数
- /// </summary>
- public int DetectTps
- {
- get; set;
- }
- /// <summary>
- /// 每次检测间隔时间
- /// </summary>
- public int IntervalTime
- {
- get; set;
- }
- /// <summary>
- /// 是否将检测的图片保存下来
- /// </summary>
- public bool IsSaveDetectImage { get; private set; }
- /// <summary>
- /// 是否保存所有检测的图片,当为False时,则只保留最新的图像
- /// </summary>
- public bool IsSaveAllImage { get; private set; }
- /// <summary>
- /// Image Save Path
- /// </summary>
- public string ImageSavePath { get; private set; }
- static VetHeartDiagnosis()
- {
- try
- {
- foreach (var aiDll in _aiDllDict)
- {
- var version = FileVersionInfo.GetVersionInfo(aiDll.Value).FileVersion.ToString();
- _aiVersionDict.Add(aiDll.Key, version);
- }
- AllFunctions = new List<FunctionInfo>
- {
- new FunctionInfo(EnumVetHeartDiagnosisFunction.VetHeartDiagnosis,true,Assembly.GetExecutingAssembly().GetName().Version.ToString(),null,new List<EngineInfo>
- {
- new EngineInfo(EnumVetHeartDiagnosisEngineName.VetHeartLVStudy,EnumVetHeartDiagnosisEngineType.VetHeartLVStudy,true,_aiVersionDict[EnumVetHeartDiagnosisEngineType.VetHeartLVStudy],_vendor,null, _relatedDllList),
- new EngineInfo(EnumVetHeartDiagnosisEngineName.VetHeartEPSS,EnumVetHeartDiagnosisEngineType.VetHeartEPSS,true,_aiVersionDict[EnumVetHeartDiagnosisEngineType.VetHeartEPSS],_vendor,null, _relatedDllList),
- new EngineInfo(EnumVetHeartDiagnosisEngineName.VetHeartEndDiastoleEndSystole,EnumVetHeartDiagnosisEngineType.VetHeartEndDiastoleEndSystole,true,_aiVersionDict[EnumVetHeartDiagnosisEngineType.VetHeartEndDiastoleEndSystole],_vendor,null, _relatedDllList),
- }),
- };
- }
- catch
- {
- }
- }
- public static void Init(FunctionInfo enabledFunction, FunctionInfo currentUsedFunction)
- {
- _enabledFunction = enabledFunction;
- _currentUsedFunction = currentUsedFunction;
- }
- /// <summary>
- /// 当启用时切换使用的引擎(静态方法,当未启用时)
- /// </summary>
- /// <param name="functionInfo"></param>
- public static void SwitchAIEngines(FunctionInfo functionInfo)
- {
- //ToDoFelix
- }
- /// <summary>
- /// Initialize VetHeartDiagnosis
- /// </summary>
- /// <param name="cpuNumber">指定用于AI计算的cpu数.</param>
- /// <param name="modelFileFolder">模型文件路径.</param>
- /// <param name="detectMode">TimesPerSecond: 按每秒固定次数间隔,PeriodicIntervals:按固定时间间隔检测.</param>
- /// <param name="detectTps">检测帧频间隔,detectModel为TimesPerSecond时使用</param>
- /// <param name="intervalTime">检测间隔时间,detectModel为PeriodicIntervals时使用.</param>
- public void Init(bool isSaveDetectImage, bool isSaveAllImage, string imageSavePath, IImageProviderV2 usImageProvider, int cpuNumber, string modelFileFolder, EnumDetectMode detectMode, int detectTps, int intervalTime)
- {
- //Load VetHeartDiagnosis
- try
- {
- IsSaveDetectImage = isSaveDetectImage;
- IsSaveAllImage = isSaveAllImage;
- ImageSavePath = imageSavePath;
- DetectMode = detectMode;
- DetectTps = detectTps;
- IntervalTime = intervalTime;
- _usImageProvider = usImageProvider;
- var config = new InferenceConfig();
- config.SetConfig(EnumInferenceConfigKey.CPU_THREADS_NUM_PER_NET, cpuNumber.ToString(), EnumDeviceType.CPU);
- CloseDiagnosis();
- var task1 = Task.Run(() =>
- {
- LoadLVStudy(modelFileFolder, config);
- });
- var task2 = Task.Run(() =>
- {
- LoadEPSS(modelFileFolder, config);
- });
- var task3 = Task.Run(() =>
- {
- LoadEDES(modelFileFolder, config);
- });
- Task.WhenAll(task1, task2, task3).GetAwaiter().GetResult();
- }
- catch (Exception ex)
- {
- throw new Exception($"Load VetHeartDiagnosis Failed!:{ex}");
- }
- }
- private void LoadLVStudy(string modelFileFolder, InferenceConfig config)
- {
- try
- {
- var vetHeartLVStudy = new VetHeartLVStudy(modelFileFolder, config);
- vetHeartLVStudy.NotifyLog += OnNotifyLog;
- _moduleDict.Add(EnumVetHeartDiagnosisEngineType.VetHeartLVStudy, vetHeartLVStudy);
- }
- catch (Exception ex)
- {
- OnNotifyLog(this, new LogEventArgs(EnumLogType.ErrorLog, $"Load VetHeartLVStudy Failed!:{ex}"));
- }
- }
- private void LoadEPSS(string modelFileFolder, InferenceConfig config)
- {
- try
- {
- var vetHeartEPSS = new VetHeartEPSS(modelFileFolder, config);
- vetHeartEPSS.NotifyLog += OnNotifyLog;
- _moduleDict.Add(EnumVetHeartDiagnosisEngineType.VetHeartEPSS, vetHeartEPSS);
- }
- catch (Exception ex)
- {
- OnNotifyLog(this, new LogEventArgs(EnumLogType.ErrorLog, $"Load VetHeartEPSS Failed!:{ex}"));
- }
- }
- private void LoadEDES(string modelFileFolder, InferenceConfig config)
- {
- try
- {
- var vetHeartEndDiastoleEndSystole = new VetHeartEndDiastoleEndSystole(modelFileFolder, config);
- vetHeartEndDiastoleEndSystole.NotifyLog += OnNotifyLog;
- _moduleDict.Add(EnumVetHeartDiagnosisEngineType.VetHeartEndDiastoleEndSystole, vetHeartEndDiastoleEndSystole);
- }
- catch (Exception ex)
- {
- OnNotifyLog(this, new LogEventArgs(EnumLogType.ErrorLog, $"Load VetHeartEndDiastoleEndSystole Failed!:{ex}"));
- }
- }
- /// <summary>
- /// 当启用时切换使用的引擎
- /// </summary>
- /// <param name="functionInfo"></param>
- public void SwitchAIEngines2(FunctionInfo functionInfo)
- {
- //ToDoFelix
- }
- /// <summary>
- /// Start the Image Provider
- /// </summary>
- public void Start()
- {
- ResetParameters();
- if (_usImageProvider != null)
- {
- _usImageProvider.ImageProvided += OnImageProvided;
- _usImageProvider.Start();
- }
- }
- /// <summary>
- /// Stop the Image Provider
- /// </summary>
- public void Stop()
- {
- if (_usImageProvider != null)
- {
- _usImageProvider.ImageProvided -= OnImageProvided;
- _usImageProvider.Stop();
- }
- }
- /// <summary>
- /// Stop the Image Provider and Close the VetHeartMLine Diagnosis
- /// </summary>
- public void Close()
- {
- Stop();
- _handlingImageEvent.WaitOne();
- lock (_detectObject)
- {
- CloseDiagnosis();
- }
- }
- /// <summary>
- /// 开启处理,并返回处理ID
- /// </summary>
- /// <param name="typeName">Modlue Name</param>
- public string StartProcess(EnumVetHeartDiagnosisEngineType typeName)
- {
- if (_moduleDict.ContainsKey(typeName))
- {
- if (_processIdDict.ContainsKey(typeName))
- {
- var existProcessId = _processIdDict[typeName];
- _processIdDict.Remove(typeName);
- _moduleDict[typeName].EndProcess(existProcessId);
- }
- return _moduleDict[typeName].StartProcess();
- }
- else
- {
- return null;
- }
- }
- /// <summary>
- /// 结束处理
- /// </summary>
- /// <param name="typeName">Type Name</param>
- public void EndProcess(EnumVetHeartDiagnosisEngineType typeName, string processId)
- {
- if (_moduleDict.ContainsKey(typeName))
- {
- if (_processIdDict.ContainsKey(typeName))
- {
- _processIdDict.Remove(typeName);
- }
- _moduleDict[typeName].EndProcess(processId);
- }
- }
- /// <summary>
- /// 检测单张图片
- /// </summary>
- /// <param name="typeName">type Name</param>
- /// <param name="inputDatas">输入数据</param>
- public IReadOnlyDictionary<IDataId, IReadOnlyList<IResultData>> DetectOneImage(EnumVetHeartDiagnosisEngineType typeName, string processId, IImageInputData inputDatas)
- {
- return HandleImage(false, typeName, processId, inputDatas);
- }
- private void OnImageProvided(object sender, IImageInputData e)
- {
- if (sender is IImageProviderV2 imageProvider)
- {
- EnumVetHeartDiagnosisEngineType? type = null;
- if (imageProvider.EngineType == EnumVetHeartDiagnosisEngineType.VetHeartLVStudy.ToString())
- {
- type = EnumVetHeartDiagnosisEngineType.VetHeartLVStudy;
- }
- else if (imageProvider.EngineType == EnumVetHeartDiagnosisEngineType.VetHeartEPSS.ToString())
- {
- type = EnumVetHeartDiagnosisEngineType.VetHeartEPSS;
- }
- else if (imageProvider.EngineType == EnumVetHeartDiagnosisEngineType.VetHeartEndDiastoleEndSystole.ToString())
- {
- type = EnumVetHeartDiagnosisEngineType.VetHeartEndDiastoleEndSystole;
- }
- if (type.HasValue)
- {
- if (!_processIdDict.ContainsKey(type.Value))
- {
- var processId = _moduleDict[type.Value].StartProcess();
- _processIdDict.Add(type.Value, processId);
- }
- OnUsImageChanged(type.Value, _processIdDict[type.Value], e);
- }
- }
- }
- private void OnUsImageChanged(EnumVetHeartDiagnosisEngineType typeName, string processId, IImageInputData inputDatas)
- {
- if (DetectMode == EnumDetectMode.TimesPerSecond)///检测模式:每秒检测几次
- {//计算fps, 3秒检测一次
- if (_startTickCount == -1)
- {
- _startTickCount = Environment.TickCount;
- HandleImage(true, typeName, processId, inputDatas);
- }
- else
- {
- var fpscurrentTickCount = Environment.TickCount;
- var timespan = fpscurrentTickCount - _startTickCount;
- if (timespan >= 3000)
- {
- _displayFps = _imageCounter * 1000 / timespan;
- _detectInterval = (int)Math.Round((float)_displayFps / DetectTps);
- _imageCounter = 0;
- _startTickCount = Environment.TickCount; ;
- }
- if (_detectInterval > 0)
- {
- if (_imageCounter % _detectInterval == 0)
- {
- HandleImage(true, typeName, processId, inputDatas);
- }
- }
- }
- _imageCounter++;
- if (_imageCounter > 1000000)
- {
- _imageCounter = 0;
- }
- }
- else///检测模式:间隔固定时间检测
- {
- if (_startTickCount == -1)
- {
- _startTickCount = Environment.TickCount;
- HandleImage(true, typeName, processId, inputDatas);
- }
- else
- {
- var currentTickCount = Environment.TickCount;
- if (IntervalTime <= currentTickCount - _startTickCount)
- {
- HandleImage(true, typeName, processId, inputDatas);
- _startTickCount = Environment.TickCount;
- }
- }
- }
- }
- private IReadOnlyDictionary<IDataId, IReadOnlyList<IResultData>> HandleImage(bool isImageProviderMode, EnumVetHeartDiagnosisEngineType typeName, string processId, IImageInputData inputData)
- {
- _handlingImageEvent.Reset();
- IReadOnlyDictionary<IDataId, IReadOnlyList<IResultData>> diagResult = default;
- try
- {
- if (isImageProviderMode)
- {
- StartEvaluation?.Invoke(this, EventArgs.Empty);
- }
- lock (_detectObject)
- {
- if (IsSaveDetectImage && !string.IsNullOrEmpty(ImageSavePath))
- {
- if (!IsSaveAllImage)
- {
- RawImageHelper.ClearOldImages(_aiType, ImageSavePath);
- }
- RawImageHelper.SaveRawImageV2(inputData.Image, _aiType, ImageSavePath);
- }
- using (inputData.Image)
- {
- if (_moduleDict.ContainsKey(typeName))
- {
- diagResult = _moduleDict[typeName].PushOnePieceOfData(processId, new InputDataContainer(inputData));
- }
- }
- }
- if (isImageProviderMode)
- {
- FinishEvaluation?.Invoke(this, diagResult);
- }
- }
- catch (Exception ex)
- {
- NotifyLog?.Invoke(this, new LogEventArgs(EnumLogType.ErrorLog, $"HandleImage Error: {ex}"));
- }
- finally
- {
- _handlingImageEvent.Set();
- }
- return diagResult;
- }
- private void OnNotifyLog(object sender, LogEventArgs e)
- {
- NotifyLog?.Invoke(this, e);
- }
- private void ResetParameters()
- {
- _startTickCount = -1;
- _imageCounter = 0;
- _displayFps = -1;
- _detectInterval = 0;
- }
- private void CloseDiagnosis()
- {
- foreach (var module in _moduleDict.Values)
- {
- module.NotifyLog -= OnNotifyLog;
- module.Dispose();
- }
- _moduleDict.Clear();
- }
- }
- }
|