URMAnalysisManager.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using SixLabors.ImageSharp;
  5. using SixLabors.ImageSharp.Processing;
  6. using Vinno.DataTypes;
  7. using Vinno.Infrastructure;
  8. using Vinno.Models.Base.Parameters;
  9. using WingInterfaceLibrary.Request.Lock;
  10. using WingInterfaceLibrary.Request.RemedicalAISelected;
  11. using WingServerCommon.Config;
  12. using WingServerCommon.Log;
  13. using WingServerCommon.Utilities;
  14. namespace WingAIDiagnosisService.URMManage
  15. {
  16. public partial class URMAnalysisManager
  17. {
  18. private LockManager _lockManager;
  19. private Action<string, string, string> OnSendDiskSpaceFullNotification;
  20. public URMAnalysisManager(Action<string, string, string> funSendDiskSpaceFullNotification)
  21. {
  22. OnSendDiskSpaceFullNotification = funSendDiskSpaceFullNotification;
  23. AppendEnvironmentPath();
  24. WatchingVideoProcessor();
  25. _lockManager = new LockManager();
  26. }
  27. public URMAnalysisV2Result DoURMAnalysis(string remedicalCode, List<string> arguments, string outputFolder, string coverFile, string userCode)
  28. {
  29. WingServerCommon.Log.Logger.WriteLineInfo($"AIService URMAnalysisManager DoURMAnalysis start, remedicalCode:{remedicalCode}");
  30. var urmAnalysisProcess = new URMAnalysisProcess();
  31. try
  32. {
  33. var arg2Params = arguments;
  34. WingServerCommon.Log.Logger.WriteLineInfo($"AIService URMAnalysisManager DoURMAnalysis, remedicalCode:{remedicalCode}, arg2Params:{arg2Params.Count}");
  35. // var familyName = "Linear";
  36. // var typeInfo = "Linear_U5-15LE";
  37. // var nativeId = "Breast";
  38. // var VecLens = 568;
  39. // var Mlas = 128;
  40. // var FramesGot = 2200;
  41. // var CenterFrequencyMhz = 4.7;
  42. // var SupersonicSpeed = 1540;
  43. // var FrequencyMin = 6.5;
  44. // var FrameRateDisplay = 101.9;
  45. // var Depth = 0;
  46. // var X0 = 0;
  47. // var Z0 = 0;
  48. // var ProbeType = "1";
  49. // var ScaleOfPixel_x = 0.214925914347303;
  50. // var ScaleOfPixel_y = 0.61038961038961;
  51. // var section = "URMAnalysisParam:Level4";
  52. // var MOCOYN = "0";
  53. // var MidProc_DeciFactor = 1;
  54. // var VectorStartForMid = 11;
  55. // var isliner = false;
  56. // // 前端调用时传入
  57. // var startX = 47;
  58. // var startY = 14;
  59. // var width = 74;
  60. // var height = 492;
  61. // int? CustomizedStartFrame = null;
  62. // int? CustomizedEndFrame = null;
  63. var UrmDatapath = arg2Params[0];
  64. var familyName = arg2Params[1];
  65. var typeInfo = arg2Params[2];
  66. var nativeId = arg2Params[3];
  67. var VecLens = ConvertToInt(arg2Params[4]);
  68. var Mlas = ConvertToInt(arg2Params[5]);
  69. var FramesGot = ConvertToInt(arg2Params[6]);
  70. var CenterFrequencyMhz = ConvertToDouble(arg2Params[7]);
  71. var SupersonicSpeed = ConvertToInt(arg2Params[8]);
  72. var FrequencyMin = ConvertToDouble(arg2Params[9]);
  73. var FrameRateDisplay = ConvertToDouble(arg2Params[10]);
  74. var Depth = ConvertToDouble(arg2Params[11]);
  75. var X0 = ConvertToDouble(arg2Params[12]);
  76. var Z0 = ConvertToDouble(arg2Params[13]);
  77. var ProbeType = arg2Params[14];
  78. var ScaleOfPixel_x = ConvertToDouble(arg2Params[15]);
  79. var ScaleOfPixel_y = ConvertToDouble(arg2Params[16]);
  80. var section = arg2Params[17];
  81. var MOCOYN = arg2Params[18];
  82. var MidProc_DeciFactor = ConvertToInt(arg2Params[19]);
  83. var VectorStartForMid = ConvertToInt(arg2Params[20]);
  84. var isliner = arg2Params[21]?.ToLower() == "true";
  85. // 前端调用时传入
  86. var startX = ConvertToInt(arg2Params[22]);
  87. var startY = ConvertToInt(arg2Params[23]);
  88. var width = ConvertToInt(arg2Params[24]);
  89. var height = ConvertToInt(arg2Params[25]);
  90. int? CustomizedStartFrame = ConvertToIntCanNull(arg2Params[26]);
  91. int? CustomizedEndFrame = ConvertToIntCanNull(arg2Params[27]);
  92. var roiXPercent = ConvertToDouble(arg2Params[28]);
  93. var roiYPercent = ConvertToDouble(arg2Params[29]);
  94. var roiWPercent = ConvertToDouble(arg2Params[30]);
  95. var roiHPercent = ConvertToDouble(arg2Params[31]);
  96. // 开始执行分析
  97. WingServerCommon.Log.Logger.WriteLineInfo($"AIService URMAnalysisManager DoURMAnalysis URMFileIO start, remedicalCode:{remedicalCode}");
  98. URMFileIO urmFileIO = new URMFileIO(familyName: familyName, typeInfo: typeInfo, nativeId: nativeId);
  99. urmFileIO.UpdateParamJson(UrmDatapath, VecLens, Mlas, FramesGot, CenterFrequencyMhz, SupersonicSpeed, FrequencyMin, FrameRateDisplay, Depth, X0, Z0, ProbeType, ScaleOfPixel_x, ScaleOfPixel_y, section, MOCOYN, MidProc_DeciFactor, VectorStartForMid, startX, startY, width, height, CustomizedStartFrame, CustomizedEndFrame, out string urmParams, out double urmRes);
  100. WingServerCommon.Log.Logger.WriteLineInfo($"AIService URMAnalysisManager DoURMAnalysis URMAnalysisModeRecord start, remedicalCode:{remedicalCode},urmParams:{urmParams}");
  101. var modeRecord = new URMAnalysisModeRecord();
  102. modeRecord.URMRes = urmRes;
  103. if (!Directory.Exists(outputFolder))
  104. {
  105. Directory.CreateDirectory(outputFolder);
  106. }
  107. WingServerCommon.Log.Logger.WriteLineInfo($"AIService URMAnalysisManager DoURMAnalysis URMAnalysis start, remedicalCode:{remedicalCode}");
  108. bool success = urmAnalysisProcess.URMAnalysis(urmParams, modeRecord);
  109. WingServerCommon.Log.Logger.WriteLineInfo($"AIService URMAnalysisManager DoURMAnalysis URMAnalysis end, remedicalCode:{remedicalCode}, success:{success}");
  110. if (success)
  111. {
  112. // 读取输出
  113. WingServerCommon.Log.Logger.WriteLineInfo($"AIService URMAnalysisManager DoURMAnalysis WriteFile start, remedicalCode:{remedicalCode}");
  114. var SrcWidth = modeRecord.URMSrcWidth;
  115. var SrcHeight = modeRecord.URMSrcHeight;
  116. var denPath = Path.Combine(outputFolder, "srcDenArray.bin");
  117. var dirPath = Path.Combine(outputFolder, "srcDirArray.bin");
  118. var velPath = Path.Combine(outputFolder, "srcVelArray.bin");
  119. var angelPath = Path.Combine(outputFolder, "srcAngleArray.bin");
  120. var maskPath = Path.Combine(outputFolder, "srcMaskArray.bin");
  121. var pointsPath = Path.Combine(outputFolder, "URMPoints.bin");
  122. var pointNumsPath = Path.Combine(outputFolder, "URMPointNums.bin");
  123. ResultDataIOHelper.WriteArrayToFile(denPath, modeRecord.URMDenArray, SrcWidth * SrcHeight);
  124. ResultDataIOHelper.WriteArrayToFile(dirPath, modeRecord.URMDirArray, SrcWidth * SrcHeight);
  125. ResultDataIOHelper.WriteArrayToFile(velPath, modeRecord.URMVelArray, SrcWidth * SrcHeight);
  126. ResultDataIOHelper.WriteArrayToFile(angelPath, modeRecord.URMAngleImgArray, SrcWidth * SrcHeight);
  127. ResultDataIOHelper.WriteByteArrayToFile(maskPath, modeRecord.URMMask, SrcWidth * SrcHeight);
  128. ResultDataIOHelper.WriteURMPointsToFile(pointsPath, modeRecord.URMPoints);
  129. ResultDataIOHelper.WriteURMPointNumsToFile(pointNumsPath, modeRecord.URMPointNums);
  130. WingServerCommon.Log.Logger.WriteLineInfo($"AIService URMAnalysisManager DoURMAnalysis DoUrmProcess start, remedicalCode:{remedicalCode}");
  131. int coverImageWidth = 0;
  132. int coverImageHeight = 0;
  133. using (var image = Image.Load(coverFile))
  134. {
  135. coverImageWidth = image.Width;
  136. coverImageHeight = image.Height;
  137. }
  138. double urmMinVal = 0;
  139. double urmMaxVal = 0;
  140. var urmProcessRequest = new UrmProcessRequest
  141. {
  142. FamilyName = familyName,
  143. TypeInfo = typeInfo,
  144. NativeId = nativeId,
  145. Isliner = isliner,
  146. ScaleOfPixel_x = ScaleOfPixel_x,
  147. ScaleOfPixel_y = ScaleOfPixel_y,
  148. Urmsrcwidth = SrcWidth,
  149. Urmsrcheight = SrcHeight,
  150. DenDataPath = denPath,
  151. DirDataPath = dirPath,
  152. VelDataPath = velPath,
  153. AngleDataPath = angelPath,
  154. MaskDataPath = maskPath,
  155. Res = modeRecord.URMRes,
  156. UrmImageType = "0",
  157. UrmBlend = 0,
  158. DownsampleIndex = 3,
  159. IntPowerDen = 4,
  160. IntPowerDir = 4,
  161. SigmaGauss = 2,
  162. VessScale = 2.4f,
  163. VelMaxScaler = 1,
  164. VelMinScaler = 0,
  165. Iterations = 1,
  166. ImgProcessVer = 1,
  167. ZoomOn = false,
  168. ZoomRoix = 0,
  169. ZoomRoiy = 0,
  170. ZoomRoiwidth = 1,
  171. ZoomRoiheight = 1,
  172. LeftRight = false,
  173. UpDown = false,
  174. UrmTraceDPoints = new DPoint[] { },
  175. Roix = (int)(coverImageWidth * roiXPercent),
  176. Roiy = (int)(coverImageHeight * roiYPercent),
  177. Roiwidth = (int)(coverImageWidth * roiWPercent),
  178. Roiheight = (int)(coverImageHeight * roiHPercent),
  179. ScreenWidth = coverImageWidth,
  180. ScreenHeight = coverImageHeight,
  181. GUID = Guid.NewGuid().ToString("N"),
  182. };
  183. if (typeInfo.ToLower() == "convex_s1-8cm")
  184. {
  185. urmProcessRequest.DownsampleIndex = 1;
  186. urmProcessRequest.IntPowerDen = 3;
  187. urmProcessRequest.IntPowerDir = 3;
  188. urmProcessRequest.SigmaGauss = 2.5f;
  189. urmProcessRequest.VessScale = 1.5f;
  190. urmProcessRequest.VelMaxScaler = 1;
  191. urmProcessRequest.VelMinScaler = 0;
  192. }
  193. var result = DoUrmProcess(urmProcessRequest).Result;
  194. var mergeFilePath = coverFile;
  195. if (!string.IsNullOrWhiteSpace(result.Base64String))
  196. {
  197. WingServerCommon.Log.Logger.WriteLineInfo($"AIService URMAnalysisManager DoURMAnalysis Merge ConverImage start, remedicalCode:{remedicalCode}");
  198. mergeFilePath = Path.Combine(outputFolder, $"{Guid.NewGuid():N}.png");
  199. using (var image1 = Image.Load(coverFile))
  200. {
  201. // 将base64字符串转换为字节数组
  202. byte[] bytes = Convert.FromBase64String(result.Base64String);
  203. // 将字节数组转换为Image对象
  204. using (var image2 = Image.Load(bytes))
  205. {
  206. // 将第二张图片画在第一张图片上
  207. image1.Mutate(ctx => ctx.DrawImage(image2, new Point(0, 0), 1f));
  208. // 保存合成后的图片
  209. image1.Save(mergeFilePath);
  210. }
  211. }
  212. }
  213. var outMsg = new URMAnalysisV2Result
  214. {
  215. URMSrcWidth = modeRecord.URMSrcWidth,
  216. URMSrcHeight = modeRecord.URMSrcHeight,
  217. URMRes = modeRecord.URMRes,
  218. ConverImageUrl = mergeFilePath,
  219. URMScaleOfPixel_x = modeRecord.URMScaleOfPixel_x,
  220. URMScaleOfPixel_y = modeRecord.URMScaleOfPixel_y,
  221. };
  222. WingServerCommon.Log.Logger.WriteLineInfo($"AIService URMAnalysisManager DoURMAnalysis end, remedicalCode:{remedicalCode}, outMsg:{outMsg}");
  223. return outMsg;
  224. }
  225. else
  226. {
  227. WingServerCommon.Log.Logger.WriteLineError($"AIService URMAnalysisManager DoURMAnalysis fail, remedicalCode:{remedicalCode}, success:{success}");
  228. }
  229. }
  230. catch (Exception ex)
  231. {
  232. if (ex.Message.Contains("磁盘空间不足"))
  233. {
  234. WingServerCommon.Log.Logger.WriteLineError($"AIService URMAnalysisManager DoURMAnalysis error, remedicalCode:{remedicalCode}, ex:{ex}");
  235. OnSendDiskSpaceFullNotification?.Invoke(userCode, remedicalCode, ex.Message);
  236. }
  237. else
  238. {
  239. WingServerCommon.Log.Logger.WriteLineWarn($"AIService URMAnalysisManager DoURMAnalysis error, remedicalCode:{remedicalCode}, ex:{ex}");
  240. }
  241. }
  242. finally
  243. {
  244. urmAnalysisProcess?.ProcessDispose();
  245. WingServerCommon.Log.Logger.WriteLineInfo($"AIService URMAnalysisManager DoURMAnalysis finally, remedicalCode:{remedicalCode}");
  246. }
  247. return null;
  248. }
  249. private void AppendEnvironmentPath()
  250. {
  251. var urmFolder = Path.Combine(ServiceManager.RootPath, "URM");
  252. var urmRunFolder = Path.Combine(ServiceManager.RootPath, "URM", "net6.0");
  253. var privatePath = @$"C:\VinnoAppLab\Depends;C:\VinnoAppLab\ipp_2018;AIMeasure;AI;Depends;DicomMpeg;Syncfusion;RemoteDiagnosis;vCloud;Test;VFetus;{urmFolder};{urmRunFolder};";
  254. bool enforcePentiumMode = false;
  255. string workPathPerCPU = string.Empty;
  256. string workPathForGPU = string.Empty;
  257. workPathPerCPU = Path.Combine(ServiceManager.RootPath, "NON_PENTIUM");
  258. privatePath = privatePath + ";" + workPathPerCPU + ";";
  259. string gpuName = string.Empty;
  260. workPathForGPU = Path.Combine(ServiceManager.RootPath, "NVIDIA");
  261. if (!string.IsNullOrEmpty(workPathForGPU))
  262. {
  263. privatePath = privatePath + workPathForGPU + ";";
  264. }
  265. if (!string.IsNullOrEmpty(privatePath))
  266. {
  267. string path = Environment.GetEnvironmentVariable("PATH");
  268. string newPath = string.Empty;
  269. if (path != null)
  270. {
  271. string upperPath = path.ToUpper();
  272. var subPathes = privatePath.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
  273. foreach (var subPath in subPathes)
  274. {
  275. VinnoDirectoryInfo dir = null;
  276. if (Path.IsPathRooted(subPath))
  277. {
  278. dir = new VinnoDirectoryInfo(subPath);
  279. }
  280. else
  281. {
  282. dir = new VinnoDirectoryInfo(Path.Combine(ServiceManager.RootPath, subPath));
  283. }
  284. if (dir.Exists)
  285. {
  286. var fullName = dir.FullName;
  287. if (!upperPath.Contains(fullName.ToUpper()))
  288. {
  289. newPath += ";" + fullName;
  290. }
  291. }
  292. }
  293. if (!string.IsNullOrEmpty(newPath))
  294. {
  295. Environment.SetEnvironmentVariable("PATH", newPath + ";" + path, EnvironmentVariableTarget.Process);
  296. }
  297. }
  298. }
  299. }
  300. private int ConvertToInt(string value)
  301. {
  302. if (string.IsNullOrWhiteSpace(value))
  303. {
  304. return 0;
  305. }
  306. if (int.TryParse(value, out int x))
  307. {
  308. return x;
  309. }
  310. return 0;
  311. }
  312. private int? ConvertToIntCanNull(string value)
  313. {
  314. if (string.IsNullOrWhiteSpace(value))
  315. {
  316. return null;
  317. }
  318. if (int.TryParse(value, out int x))
  319. {
  320. return x;
  321. }
  322. return 0;
  323. }
  324. private double ConvertToDouble(string value)
  325. {
  326. if (string.IsNullOrWhiteSpace(value))
  327. {
  328. return 0;
  329. }
  330. if (double.TryParse(value, out double x))
  331. {
  332. return x;
  333. }
  334. return 0;
  335. }
  336. }
  337. }