AIDiagnosisService.URM.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. using WingServerCommon.Service;
  2. using WingInterfaceLibrary.Interface;
  3. using WingInterfaceLibrary.Request.RemedicalAISelected;
  4. using System.Threading.Tasks;
  5. using System.Linq;
  6. using WingServerCommon.Log;
  7. using System.IO;
  8. using System;
  9. using System.Net.Http;
  10. using System.Net;
  11. using WingAIDiagnosisService.URMManage;
  12. using System.Collections.Generic;
  13. using WingInterfaceLibrary.Request.Examine;
  14. using System.Drawing;
  15. using Vinno.IUS.Common.Media.FFmpeg.Video;
  16. using Vinno.IUS.Common.Media.FFmpeg.Video.Codecs;
  17. using SkiaSharp;
  18. using Vinno.IUS.Common.Media.FFmpeg.Settings;
  19. namespace WingAIDiagnosisService.Service
  20. {
  21. /// <summary>
  22. /// URM分析服务
  23. /// </summary>
  24. public partial class AIDiagnosisService : JsonRpcService, IAIDiagnosisService
  25. {
  26. private static object _urmProcessLocker = new object();
  27. private readonly string _urmTempFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "URMTemp");
  28. /// <summary>
  29. /// URM分析
  30. /// </summary>
  31. /// <param name="request">URM分析请求实体</param>
  32. /// <returns>URM分析分析结果</returns>
  33. /// <value></value>
  34. /// <errorCodes></errorCodes>
  35. public async Task<URMAnalysisResult> URMAnalysisAsync(URMAnalysisRequest request)
  36. {
  37. var remedicalCode = request.RemedicalCode;
  38. var pos = $"{request.X},{request.Y},{request.Width},{request.Height}";
  39. Logger.WriteLineInfo($"AIDiagnosisService URMAnalysisAsync start, remedicalCode:{remedicalCode}, Pos:{pos}");
  40. var currentFolder = string.Empty;
  41. var resultData = new URMAnalysisResult { URMAnalysisDetails = new List<ImgItem>() };
  42. try
  43. {
  44. if (!string.IsNullOrWhiteSpace(remedicalCode))
  45. {
  46. var remedical = await _remedicalDBService.GetRemedicalByCodeAsync(remedicalCode, false);
  47. var origialRemedicalInfo = remedical?.ImgList?.FirstOrDefault(x => x.ImgType == 0);
  48. var fileToken = origialRemedicalInfo?.FileToken ?? string.Empty;
  49. if (!string.IsNullOrWhiteSpace(fileToken))
  50. {
  51. Logger.WriteLineInfo($"AIDiagnosisService URMAnalysisAsync, remedicalCode:{remedicalCode}, fileToken:{fileToken}");
  52. var origialName = Path.GetFileName(fileToken);
  53. currentFolder = Path.Combine(_urmTempFolder, remedicalCode);
  54. if (!Directory.Exists(currentFolder))
  55. {
  56. Directory.CreateDirectory(currentFolder);
  57. }
  58. var origialFile = Path.Combine(currentFolder, origialName);
  59. if (!File.Exists(origialFile))
  60. {
  61. await DownloadToLocalAsync(fileToken, origialFile);
  62. }
  63. if (File.Exists(origialFile))
  64. {
  65. Logger.WriteLineInfo($"AIDiagnosisService URMAnalysisAsync download success, remedicalCode:{remedicalCode}, fileToken:{fileToken}, localFile:{origialFile}");
  66. bool success = false;
  67. lock (_urmProcessLocker)
  68. {
  69. Logger.WriteLineInfo($"AIDiagnosisService URMAnalysisAsync URMAnalysisProcess start, remedicalCode:{remedicalCode}");
  70. URMAnalysisProcess _urmAnalysisProcess = null;
  71. try
  72. {
  73. // 开始URM分析
  74. _urmAnalysisProcess = new URMAnalysisProcess();
  75. success = _urmAnalysisProcess.URMAnalysis($"\"UrmDatapath\":\"{origialFile}\",\"VecLens\":\"474\",\"Mlas\":\"128\",\"VectorStartForMid\":\"9\",\"FramesGot\":\"1200\",\"CenterFrequencyMHz\":\"3.8\",\"Prf\":\"10313\",\"Angles\":\"29\",\"SupersonicSpeed\":\"1540\",\"PulseNum\":\"3\",\"FrequencyMin\":\"5\",\"FMUint\":\"MHz\",\"FrameRateDisplay\":\"101.9\",\"FDUnit\":\"Hz\",\"ScaleOfPixel_x\":\"0.212260852677748\",\"ScaleOfPixel_y\":\"0.493506493506494\",\"ULMCount\":\"400\",\"PacketsNum\":\"200\",\"Res\":\"2.5\",\"MaxLinkingDistance\":\"2\",\"MinLength\":\"5\",\"MaxGapClosing\":\"2\",\"LocMethod\":\"radial\",\"ButterCuttofFreqLow\":\"30\",\"NLocalMax\":\"3\",\"SVDCutoffLow\":\"30\",\"Fwhm\":\"3\",\"MOCOYN\":\"0\",\"MOCOLevel\":\"4\",\"MOCOThresh1\":\"0.05\",\"MOCOThresh2\":\"0.05\",\"MOCOThresh3\":\"5\",\"LocaFixmethod\":\"fixgray\",\"LocFixThresh\":\"25\",\"RefNum\":\"1\",\"MotionCorrThresh\":\"0.5\",\"Pos\":\" {pos} \",\"FilterDeci\":\"1\",\"PSFNum\":\"10\",\"PSFCorr\":\"0.5\",\"Depth\":\"0\",\"X0\":\"0\",\"Z0\":\"0\",\"ProbeType\":\"1\",\"Decifactorx\":\"1\",\"Decifactory\":\"1\",\"SizeScan\":\"474\",\"MotionAngleThresh\":\"2\",\"TrackInterpFactor\":\"0.8\"", currentFolder);
  76. }
  77. catch (Exception ex)
  78. {
  79. Logger.WriteLineWarn($"AIDiagnosisService URMAnalysisAsync URMAnalysisProcess error, remedicalCode:{remedicalCode}, ex:{ex}");
  80. }
  81. finally
  82. {
  83. _urmAnalysisProcess?.Release();
  84. Logger.WriteLineInfo($"AIDiagnosisService URMAnalysisAsync URMAnalysisProcess end, remedicalCode:{remedicalCode}");
  85. }
  86. }
  87. if (success)
  88. {
  89. resultData.IsSuccess = true;
  90. await InitURMAnalysisDetails(resultData, fileToken, currentFolder, origialRemedicalInfo);
  91. await InitURMVideo(resultData, currentFolder);
  92. }
  93. // else
  94. // {
  95. // Logger.WriteLineWarn($"AIDiagnosisService URMAnalysisAsync URMAnalysisProcess failed test, remedicalCode:{remedicalCode}");
  96. // resultData.IsSuccess = true;
  97. // await InitURMAnalysisDetails(resultData, fileToken, currentFolder, origialRemedicalInfo);
  98. // await InitURMVideo(resultData, currentFolder);
  99. // }
  100. }
  101. }
  102. }
  103. }
  104. catch (Exception ex)
  105. {
  106. Logger.WriteLineWarn($"AIDiagnosisService URMAnalysisAsync error, remedicalCode:{remedicalCode}, ex:{ex}");
  107. }
  108. finally
  109. {
  110. if (Directory.Exists(currentFolder))
  111. {
  112. // Directory.Delete(currentFolder, true);
  113. }
  114. }
  115. Logger.WriteLineInfo($"AIDiagnosisService URMAnalysisAsync finished, remedicalCode:{remedicalCode}, result:{resultData.IsSuccess}");
  116. return resultData;
  117. }
  118. private async Task InitURMAnalysisDetails(URMAnalysisResult resultData, string originalUrl, string currentFolder, ImgItem originalRemedicalInfo)
  119. {
  120. resultData.URMAnalysisDetails.Add(new ImgItem
  121. {
  122. ImgType = 0,
  123. FileToken = originalUrl,
  124. FileSize = originalRemedicalInfo.FileSize,
  125. CoverImgUrl = originalRemedicalInfo.CoverImgUrl,
  126. PreviewFileUrl = originalRemedicalInfo.PreviewFileUrl,
  127. });
  128. var files = Directory.GetFiles(currentFolder);
  129. foreach (var file in files)
  130. {
  131. var fileName = Path.GetFileName(file);
  132. if (fileName.Contains("den"))
  133. {
  134. var fileInfo = await UploadFileWithSizeAsync(file, fileName);
  135. resultData.URMAnalysisDetails.Add(new ImgItem
  136. {
  137. ImgType = 1,
  138. FileToken = fileInfo.Item1,
  139. FileSize = fileInfo.Item2,
  140. });
  141. }
  142. if (fileName.Contains("dir"))
  143. {
  144. var fileInfo = await UploadFileWithSizeAsync(file, fileName);
  145. resultData.URMAnalysisDetails.Add(new ImgItem
  146. {
  147. ImgType = 2,
  148. FileToken = fileInfo.Item1,
  149. FileSize = fileInfo.Item2,
  150. });
  151. }
  152. if (fileName.Contains("vel"))
  153. {
  154. var fileInfo = await UploadFileWithSizeAsync(file, fileName);
  155. resultData.URMAnalysisDetails.Add(new ImgItem
  156. {
  157. ImgType = 3,
  158. FileToken = fileInfo.Item1,
  159. FileSize = fileInfo.Item2,
  160. });
  161. }
  162. }
  163. }
  164. private async Task InitURMVideo(URMAnalysisResult resultData, string currentFolder)
  165. {
  166. var mp4FileInfos = ImagesToMP4(currentFolder);
  167. if (!string.IsNullOrWhiteSpace(mp4FileInfos.Item1))
  168. {
  169. if (File.Exists(mp4FileInfos.Item1))
  170. {
  171. var mp4ImgItem = new ImgItem
  172. {
  173. ImgType = 4,
  174. };
  175. var converImageUrl = await UploadFileAsync(mp4FileInfos.Item1, Path.GetFileName(mp4FileInfos.Item1));
  176. mp4ImgItem.CoverImgUrl = converImageUrl;
  177. mp4ImgItem.PreviewFileUrl = converImageUrl;
  178. if (File.Exists(mp4FileInfos.Item2))
  179. {
  180. var mp4Info = await UploadFileWithSizeAsync(mp4FileInfos.Item2, Path.GetFileName(mp4FileInfos.Item2));
  181. mp4ImgItem.FileToken = mp4Info.Item1;
  182. mp4ImgItem.FileSize = mp4Info.Item2;
  183. resultData.URMAnalysisDetails.Add(mp4ImgItem);
  184. }
  185. }
  186. }
  187. }
  188. private Tuple<string, string> ImagesToMP4(string currentFolder)
  189. {
  190. try
  191. {
  192. var files = Directory.GetFiles(Path.Combine(currentFolder, "avi"))?.OrderBy(x => x);
  193. if (files?.Any() ?? false)
  194. {
  195. var mp4Path = Path.Combine(currentFolder, $"{Guid.NewGuid():N}.mp4");
  196. var firstFile = files.FirstOrDefault();
  197. var width = 0;
  198. var height = 0;
  199. using (SKBitmap bitmap = SKBitmap.Decode(firstFile))
  200. {
  201. width = bitmap.Width;
  202. height = bitmap.Height;
  203. }
  204. var frameRate = 10;
  205. var setting = new FFmpegSettings();
  206. var writeArgs = new FFmpegVideoWriterArgs(mp4Path, width, height)
  207. {
  208. FrameRate = frameRate,
  209. VideoCodec = FFmpegVideoCodec.X264
  210. };
  211. using (var videoWriter = new FFmpegVideoWriter(writeArgs, setting, null))
  212. {
  213. foreach (var avi in files)
  214. {
  215. using (SKBitmap bitmap = SKBitmap.Decode(avi))
  216. {
  217. if (bitmap != null)
  218. {
  219. try
  220. {
  221. if (bitmap.Bytes != null && bitmap.Bytes.Length > 0 && bitmap.Width > 0 && bitmap.Height > 0)
  222. {
  223. var frame = new BitmapFrame(bitmap.Width, bitmap.Height, bitmap.Bytes);
  224. videoWriter.WriteFrame(frame);
  225. }
  226. }
  227. catch (Exception exception)
  228. {
  229. }
  230. }
  231. }
  232. }
  233. }
  234. return new Tuple<string, string>(firstFile, mp4Path);
  235. }
  236. }
  237. catch (Exception ex)
  238. {
  239. Logger.WriteLineWarn($"AIDiagnosisService URMAnalysisAsync ImagesToMP4 ex:{ex}");
  240. }
  241. return new Tuple<string, string>("", "");
  242. }
  243. private async Task<bool> DownloadToLocalAsync(string fileUrl, string localFile)
  244. {
  245. try
  246. {
  247. if (fileUrl.Contains("FlyinsonoStorage"))
  248. {
  249. // 自建存储
  250. var infos = fileUrl.Split("FlyinsonoStorage");
  251. var sourceFilePath = Path.Combine(_storageDirectory, infos[1].Trim('/'));
  252. if (File.Exists(sourceFilePath))
  253. {
  254. File.Copy(sourceFilePath, localFile);
  255. return true;
  256. }
  257. }
  258. else
  259. {
  260. long fileSize = 0;
  261. using (var request = new HttpRequestMessage())
  262. {
  263. request.RequestUri = new Uri(fileUrl);
  264. request.Method = HttpMethod.Get;
  265. var response = await _httpClient.SendAsync(request);
  266. if (response != null && response.StatusCode == HttpStatusCode.OK)
  267. {
  268. var contentLength = response.Content.Headers.ContentLength;
  269. fileSize = contentLength == null ? 0 : contentLength.Value;
  270. }
  271. }
  272. if (fileSize > 0)
  273. {
  274. byte[] bytes = await _httpClient.GetByteArrayAsync(fileUrl);
  275. File.WriteAllBytes(localFile, bytes);
  276. return true;
  277. }
  278. }
  279. }
  280. catch (Exception ex)
  281. {
  282. Logger.WriteLineWarn($"AIDiagnosisService URMAnalysisAsync, fileToken:{fileUrl}, ex:{ex}");
  283. }
  284. return false;
  285. }
  286. }
  287. }