using System; using System.Collections.Generic; using System.IO; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Processing; using Vinno.DataTypes; using Vinno.Infrastructure; using Vinno.Models.Base.Parameters; using WingInterfaceLibrary.Request.Lock; using WingInterfaceLibrary.Request.RemedicalAISelected; using WingServerCommon.Config; using WingServerCommon.Log; using WingServerCommon.Utilities; namespace WingAIDiagnosisService.URMManage { public partial class URMAnalysisManager { private LockManager _lockManager; private Action OnSendDiskSpaceFullNotification; public URMAnalysisManager(Action funSendDiskSpaceFullNotification) { OnSendDiskSpaceFullNotification = funSendDiskSpaceFullNotification; AppendEnvironmentPath(); WatchingVideoProcessor(); _lockManager = new LockManager(); } public URMAnalysisV2Result DoURMAnalysis(string remedicalCode, List arguments, string outputFolder, string coverFile, string userCode) { WingServerCommon.Log.Logger.WriteLineInfo($"AIService URMAnalysisManager DoURMAnalysis start, remedicalCode:{remedicalCode}"); var urmAnalysisProcess = new URMAnalysisProcess(); try { var arg2Params = arguments; WingServerCommon.Log.Logger.WriteLineInfo($"AIService URMAnalysisManager DoURMAnalysis, remedicalCode:{remedicalCode}, arg2Params:{arg2Params.Count}"); // var familyName = "Linear"; // var typeInfo = "Linear_U5-15LE"; // var nativeId = "Breast"; // var VecLens = 568; // var Mlas = 128; // var FramesGot = 2200; // var CenterFrequencyMhz = 4.7; // var SupersonicSpeed = 1540; // var FrequencyMin = 6.5; // var FrameRateDisplay = 101.9; // var Depth = 0; // var X0 = 0; // var Z0 = 0; // var ProbeType = "1"; // var ScaleOfPixel_x = 0.214925914347303; // var ScaleOfPixel_y = 0.61038961038961; // var section = "URMAnalysisParam:Level4"; // var MOCOYN = "0"; // var MidProc_DeciFactor = 1; // var VectorStartForMid = 11; // var isliner = false; // // 前端调用时传入 // var startX = 47; // var startY = 14; // var width = 74; // var height = 492; // int? CustomizedStartFrame = null; // int? CustomizedEndFrame = null; var UrmDatapath = arg2Params[0]; var familyName = arg2Params[1]; var typeInfo = arg2Params[2]; var nativeId = arg2Params[3]; var VecLens = ConvertToInt(arg2Params[4]); var Mlas = ConvertToInt(arg2Params[5]); var FramesGot = ConvertToInt(arg2Params[6]); var CenterFrequencyMhz = ConvertToDouble(arg2Params[7]); var SupersonicSpeed = ConvertToInt(arg2Params[8]); var FrequencyMin = ConvertToDouble(arg2Params[9]); var FrameRateDisplay = ConvertToDouble(arg2Params[10]); var Depth = ConvertToDouble(arg2Params[11]); var X0 = ConvertToDouble(arg2Params[12]); var Z0 = ConvertToDouble(arg2Params[13]); var ProbeType = arg2Params[14]; var ScaleOfPixel_x = ConvertToDouble(arg2Params[15]); var ScaleOfPixel_y = ConvertToDouble(arg2Params[16]); var section = arg2Params[17]; var MOCOYN = arg2Params[18]; var MidProc_DeciFactor = ConvertToInt(arg2Params[19]); var VectorStartForMid = ConvertToInt(arg2Params[20]); var isliner = arg2Params[21]?.ToLower() == "true"; // 前端调用时传入 var startX = ConvertToInt(arg2Params[22]); var startY = ConvertToInt(arg2Params[23]); var width = ConvertToInt(arg2Params[24]); var height = ConvertToInt(arg2Params[25]); int? CustomizedStartFrame = ConvertToIntCanNull(arg2Params[26]); int? CustomizedEndFrame = ConvertToIntCanNull(arg2Params[27]); var roiXPercent = ConvertToDouble(arg2Params[28]); var roiYPercent = ConvertToDouble(arg2Params[29]); var roiWPercent = ConvertToDouble(arg2Params[30]); var roiHPercent = ConvertToDouble(arg2Params[31]); // 开始执行分析 WingServerCommon.Log.Logger.WriteLineInfo($"AIService URMAnalysisManager DoURMAnalysis URMFileIO start, remedicalCode:{remedicalCode}"); URMFileIO urmFileIO = new URMFileIO(familyName: familyName, typeInfo: typeInfo, nativeId: nativeId); 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); WingServerCommon.Log.Logger.WriteLineInfo($"AIService URMAnalysisManager DoURMAnalysis URMAnalysisModeRecord start, remedicalCode:{remedicalCode},urmParams:{urmParams}"); var modeRecord = new URMAnalysisModeRecord(); modeRecord.URMRes = urmRes; if (!Directory.Exists(outputFolder)) { Directory.CreateDirectory(outputFolder); } WingServerCommon.Log.Logger.WriteLineInfo($"AIService URMAnalysisManager DoURMAnalysis URMAnalysis start, remedicalCode:{remedicalCode}"); bool success = urmAnalysisProcess.URMAnalysis(urmParams, modeRecord); WingServerCommon.Log.Logger.WriteLineInfo($"AIService URMAnalysisManager DoURMAnalysis URMAnalysis end, remedicalCode:{remedicalCode}, success:{success}"); if (success) { // 读取输出 WingServerCommon.Log.Logger.WriteLineInfo($"AIService URMAnalysisManager DoURMAnalysis WriteFile start, remedicalCode:{remedicalCode}"); var SrcWidth = modeRecord.URMSrcWidth; var SrcHeight = modeRecord.URMSrcHeight; var denPath = Path.Combine(outputFolder, "srcDenArray.bin"); var dirPath = Path.Combine(outputFolder, "srcDirArray.bin"); var velPath = Path.Combine(outputFolder, "srcVelArray.bin"); var angelPath = Path.Combine(outputFolder, "srcAngleArray.bin"); var maskPath = Path.Combine(outputFolder, "srcMaskArray.bin"); var pointsPath = Path.Combine(outputFolder, "URMPoints.bin"); var pointNumsPath = Path.Combine(outputFolder, "URMPointNums.bin"); ResultDataIOHelper.WriteArrayToFile(denPath, modeRecord.URMDenArray, SrcWidth * SrcHeight); ResultDataIOHelper.WriteArrayToFile(dirPath, modeRecord.URMDirArray, SrcWidth * SrcHeight); ResultDataIOHelper.WriteArrayToFile(velPath, modeRecord.URMVelArray, SrcWidth * SrcHeight); ResultDataIOHelper.WriteArrayToFile(angelPath, modeRecord.URMAngleImgArray, SrcWidth * SrcHeight); ResultDataIOHelper.WriteByteArrayToFile(maskPath, modeRecord.URMMask, SrcWidth * SrcHeight); ResultDataIOHelper.WriteURMPointsToFile(pointsPath, modeRecord.URMPoints); ResultDataIOHelper.WriteURMPointNumsToFile(pointNumsPath, modeRecord.URMPointNums); WingServerCommon.Log.Logger.WriteLineInfo($"AIService URMAnalysisManager DoURMAnalysis DoUrmProcess start, remedicalCode:{remedicalCode}"); int coverImageWidth = 0; int coverImageHeight = 0; using (var image = Image.Load(coverFile)) { coverImageWidth = image.Width; coverImageHeight = image.Height; } double urmMinVal = 0; double urmMaxVal = 0; var urmProcessRequest = new UrmProcessRequest { FamilyName = familyName, TypeInfo = typeInfo, NativeId = nativeId, Isliner = isliner, ScaleOfPixel_x = ScaleOfPixel_x, ScaleOfPixel_y = ScaleOfPixel_y, Urmsrcwidth = SrcWidth, Urmsrcheight = SrcHeight, DenDataPath = denPath, DirDataPath = dirPath, VelDataPath = velPath, AngleDataPath = angelPath, MaskDataPath = maskPath, Res = modeRecord.URMRes, UrmImageType = "0", UrmBlend = 0, DownsampleIndex = 3, IntPowerDen = 4, IntPowerDir = 4, SigmaGauss = 2, VessScale = 2.4f, VelMaxScaler = 1, VelMinScaler = 0, Iterations = 1, ImgProcessVer = 1, ZoomOn = false, ZoomRoix = 0, ZoomRoiy = 0, ZoomRoiwidth = 1, ZoomRoiheight = 1, LeftRight = false, UpDown = false, UrmTraceDPoints = new DPoint[] { }, Roix = (int)(coverImageWidth * roiXPercent), Roiy = (int)(coverImageHeight * roiYPercent), Roiwidth = (int)(coverImageWidth * roiWPercent), Roiheight = (int)(coverImageHeight * roiHPercent), ScreenWidth = coverImageWidth, ScreenHeight = coverImageHeight, GUID = Guid.NewGuid().ToString("N"), }; if (typeInfo.ToLower() == "convex_s1-8cm") { urmProcessRequest.DownsampleIndex = 1; urmProcessRequest.IntPowerDen = 3; urmProcessRequest.IntPowerDir = 3; urmProcessRequest.SigmaGauss = 2.5f; urmProcessRequest.VessScale = 1.5f; urmProcessRequest.VelMaxScaler = 1; urmProcessRequest.VelMinScaler = 0; } var result = DoUrmProcess(urmProcessRequest).Result; var mergeFilePath = coverFile; if (!string.IsNullOrWhiteSpace(result.Base64String)) { WingServerCommon.Log.Logger.WriteLineInfo($"AIService URMAnalysisManager DoURMAnalysis Merge ConverImage start, remedicalCode:{remedicalCode}"); mergeFilePath = Path.Combine(outputFolder, $"{Guid.NewGuid():N}.png"); using (var image1 = Image.Load(coverFile)) { // 将base64字符串转换为字节数组 byte[] bytes = Convert.FromBase64String(result.Base64String); // 将字节数组转换为Image对象 using (var image2 = Image.Load(bytes)) { // 将第二张图片画在第一张图片上 image1.Mutate(ctx => ctx.DrawImage(image2, new Point(0, 0), 1f)); // 保存合成后的图片 image1.Save(mergeFilePath); } } } var outMsg = new URMAnalysisV2Result { URMSrcWidth = modeRecord.URMSrcWidth, URMSrcHeight = modeRecord.URMSrcHeight, URMRes = modeRecord.URMRes, ConverImageUrl = mergeFilePath, URMScaleOfPixel_x = modeRecord.URMScaleOfPixel_x, URMScaleOfPixel_y = modeRecord.URMScaleOfPixel_y, }; WingServerCommon.Log.Logger.WriteLineInfo($"AIService URMAnalysisManager DoURMAnalysis end, remedicalCode:{remedicalCode}, outMsg:{outMsg}"); return outMsg; } else { WingServerCommon.Log.Logger.WriteLineError($"AIService URMAnalysisManager DoURMAnalysis fail, remedicalCode:{remedicalCode}, success:{success}"); } } catch (Exception ex) { if (ex.Message.Contains("磁盘空间不足")) { WingServerCommon.Log.Logger.WriteLineError($"AIService URMAnalysisManager DoURMAnalysis error, remedicalCode:{remedicalCode}, ex:{ex}"); OnSendDiskSpaceFullNotification?.Invoke(userCode, remedicalCode, ex.Message); } else { WingServerCommon.Log.Logger.WriteLineWarn($"AIService URMAnalysisManager DoURMAnalysis error, remedicalCode:{remedicalCode}, ex:{ex}"); } } finally { urmAnalysisProcess?.ProcessDispose(); WingServerCommon.Log.Logger.WriteLineInfo($"AIService URMAnalysisManager DoURMAnalysis finally, remedicalCode:{remedicalCode}"); } return null; } private void AppendEnvironmentPath() { var urmFolder = Path.Combine(ServiceManager.RootPath, "URM"); var urmRunFolder = Path.Combine(ServiceManager.RootPath, "URM", "net6.0"); var privatePath = @$"C:\VinnoAppLab\Depends;C:\VinnoAppLab\ipp_2018;AIMeasure;AI;Depends;DicomMpeg;Syncfusion;RemoteDiagnosis;vCloud;Test;VFetus;{urmFolder};{urmRunFolder};"; bool enforcePentiumMode = false; string workPathPerCPU = string.Empty; string workPathForGPU = string.Empty; workPathPerCPU = Path.Combine(ServiceManager.RootPath, "NON_PENTIUM"); privatePath = privatePath + ";" + workPathPerCPU + ";"; string gpuName = string.Empty; workPathForGPU = Path.Combine(ServiceManager.RootPath, "NVIDIA"); if (!string.IsNullOrEmpty(workPathForGPU)) { privatePath = privatePath + workPathForGPU + ";"; } if (!string.IsNullOrEmpty(privatePath)) { string path = Environment.GetEnvironmentVariable("PATH"); string newPath = string.Empty; if (path != null) { string upperPath = path.ToUpper(); var subPathes = privatePath.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); foreach (var subPath in subPathes) { VinnoDirectoryInfo dir = null; if (Path.IsPathRooted(subPath)) { dir = new VinnoDirectoryInfo(subPath); } else { dir = new VinnoDirectoryInfo(Path.Combine(ServiceManager.RootPath, subPath)); } if (dir.Exists) { var fullName = dir.FullName; if (!upperPath.Contains(fullName.ToUpper())) { newPath += ";" + fullName; } } } if (!string.IsNullOrEmpty(newPath)) { Environment.SetEnvironmentVariable("PATH", newPath + ";" + path, EnvironmentVariableTarget.Process); } } } } private int ConvertToInt(string value) { if (string.IsNullOrWhiteSpace(value)) { return 0; } if (int.TryParse(value, out int x)) { return x; } return 0; } private int? ConvertToIntCanNull(string value) { if (string.IsNullOrWhiteSpace(value)) { return null; } if (int.TryParse(value, out int x)) { return x; } return 0; } private double ConvertToDouble(string value) { if (string.IsNullOrWhiteSpace(value)) { return 0; } if (double.TryParse(value, out double x)) { return x; } return 0; } } }