OrganSegProcess.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. using AI.Common;
  2. using AI.Common.Log;
  3. using AI.Common.Tools;
  4. using UsHepatoRenalRatioDetectLib.InferenceNetworks.Onnx;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.IO;
  8. namespace UsHepatoRenalRatioDetectLib.OrganSegProcessModule
  9. {
  10. public class OrganSegProcess : IOrganSegProcess
  11. {
  12. #region private
  13. private IInferenceNetwork _inferNet;
  14. private string _netDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Networks");
  15. private InferenceCore _inferCore = null;
  16. private volatile bool _initialized = false;
  17. #endregion
  18. #region 实现接口
  19. /// <summary>
  20. /// 构造函数
  21. /// </summary>
  22. public OrganSegProcess()
  23. {
  24. }
  25. /// <summary>
  26. /// 通知订阅者,有log要记
  27. /// </summary>
  28. public event EventHandler<LogEventArgs> NotifyLog;
  29. /// <summary>
  30. /// 通知订阅者,推理过程中发生了错误
  31. /// </summary>
  32. public event EventHandler<ErrorEventArgs> NotifyError;
  33. ///// <summary>
  34. ///// 通知订阅者,脏器分割结果有更新
  35. ///// </summary>
  36. //public event EventHandler<OrganSegUpdateEventArgs> NotifyOrganSegProcessFinish;
  37. /// <summary>
  38. /// 初始化
  39. /// </summary>
  40. /// <param name="modelNames"></param>
  41. /// <param name="modelDir"></param>
  42. /// <returns></returns>
  43. public void Init(InferenceCore inferCore, EnumDeviceType deviceType, string netDir)
  44. {
  45. _inferNet = new InferNetOnnxOrganDetectorAbdomen();
  46. if (_netDir != string.Empty && Directory.Exists(netDir))
  47. {
  48. _netDir = netDir;
  49. }
  50. _inferCore = inferCore;
  51. _initialized = true;
  52. }
  53. /// <summary>
  54. /// 加载模型
  55. /// </summary>
  56. /// <param name="modelName"></param>
  57. public void LoadGuideInferNet()
  58. {
  59. if (!_initialized)
  60. {
  61. throw new Exception("UsImageAnalyser should be initialized before use.");
  62. }
  63. try
  64. {
  65. if (!_inferNet.ModelLoaded)
  66. {
  67. //string netDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Networks");
  68. byte[] trainedNetwork = InferenceNetworkUtils.ReadNetworkDataFromFile(_netDir, _inferNet.NetworkName, _inferNet.HashCode);
  69. // 设置inferCore的参数
  70. //_inferenceCore.SetConfig(EnumInferCoreConfigKey.CPU_THREADS_NUM, numCpu.ToString(), EnumDeviceType.CPU);
  71. _inferNet.LoadNetwork(_inferCore, EnumDeviceType.CPU, trainedNetwork);
  72. }
  73. }
  74. catch (Exception excep)
  75. {
  76. throw new Exception("Failed at Loading network:" + excep);
  77. }
  78. }
  79. /// <summary>
  80. /// 卸载模型
  81. /// </summary>
  82. /// <param name="modelName"></param>
  83. public void UnLoadGuideInferNet()
  84. {
  85. if (!_initialized)
  86. {
  87. throw new Exception("UsImageAnalyser should be initialized before use.");
  88. }
  89. if (_inferNet.ModelLoaded)
  90. {
  91. _inferNet?.Dispose();
  92. }
  93. }
  94. /// <summary>
  95. /// 推理一幅图像
  96. /// </summary>
  97. /// <param name="image"></param>
  98. /// <returns></returns>
  99. public List<DetectedOrgan> EvaluateOneImage(RawImage image, bool isCropped)
  100. {
  101. List<DetectedOrgan> detectedOrgansPerImg = new List<DetectedOrgan>();
  102. if (!_initialized)
  103. {
  104. throw new Exception("UsImageAnalyser should be initialized before use.");
  105. }
  106. if (!_inferNet.ModelLoaded)
  107. {
  108. throw new Exception("InferNet should be loaded before the calling of func: EvaluateOneImage.");
  109. }
  110. Rect cropRect;
  111. if (isCropped)
  112. {
  113. cropRect = new Rect(0, 0, image.Width, image.Height);
  114. }
  115. else
  116. {
  117. if (!UsImageRegionSegHelper.CropWithCvCore(image, out cropRect))
  118. {
  119. NotifyLog?.Invoke(this, new LogEventArgs(EnumLogType.WarnLog, "Failed at UsImageRegionSegUtils.CropWithCvCore."));
  120. }
  121. }
  122. InferenceNetworkInputImage inferInput = new InferenceNetworkInputImage(image, cropRect);
  123. var inferResult = _inferNet.Process(inferInput);
  124. foreach (var detectedOb in inferResult)
  125. {
  126. var detectedObTrans = (DetectedOrgan)detectedOb;
  127. // 考虑到一幅图上同一个脏器,可能被分到多个detectedOb里,这里要把同一个脏器的多个轮廓合并到一起
  128. // 如,肝脏,在同一个mask中被分成了两部分,将作为两个DetectedOrgan输出,虽然目前只允许面积最大的连通区域作为
  129. // 最终肝脏mask输出(这种情况下不会出现多个同为肝脏的DetectedOrgan),
  130. // 但是,程序上先兼容同一个脏器被分成多个DetectedOrgan的情况,以免影响后续功能扩展
  131. var organExistIndex = detectedOrgansPerImg.FindIndex(x => x.Organ == detectedObTrans.Organ);
  132. if (organExistIndex != -1)
  133. {
  134. detectedOrgansPerImg[organExistIndex].AddContours(detectedObTrans.Confidence,
  135. detectedObTrans.BoundingBox, detectedObTrans.Contours);
  136. }
  137. else
  138. {
  139. detectedOrgansPerImg.Add(detectedObTrans);
  140. }
  141. }
  142. return detectedOrgansPerImg;
  143. }
  144. /// <summary>
  145. /// 主动销毁
  146. /// </summary>
  147. public void Dispose()
  148. {
  149. DoDispose();
  150. GC.SuppressFinalize(this);
  151. LogHelper.InfoLog("UsImageAnalyser.Disposed manually.", string.Empty);
  152. }
  153. /// <summary>
  154. /// 析构
  155. /// </summary>
  156. ~OrganSegProcess()
  157. {
  158. DoDispose();
  159. LogHelper.InfoLog("UsImageAnalyser.Disposed by destructor.", string.Empty);
  160. }
  161. #endregion
  162. #region private funcs
  163. private void OnInferNetLogWrite(object sender, LogEventArgs e)
  164. {
  165. NotifyLog?.Invoke(this, e);
  166. }
  167. private void DoDispose()
  168. {
  169. if (_inferNet != null)
  170. {
  171. _inferNet?.Dispose();
  172. _inferNet = null;
  173. }
  174. }
  175. #endregion
  176. }
  177. }