URMAnalysisManager.cs 17 KB

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