using WingServerCommon.Service; using WingInterfaceLibrary.Interface; using WingInterfaceLibrary.Request; using WingInterfaceLibrary.Enum; using WingServerCommon.Config; using WingServerCommon.Config.Parameters; using WingAIDiagnosisService.Carotid.Utilities; using Vinno.vCloud.Common.Vid2; using WingAIDiagnosisService.Manage; using WingAIDiagnosisService.Carotid; using Newtonsoft.Json; using AI.DiagSystem; using WingServerCommon.Log; using System.IO; using System; using System.Threading.Tasks; using System.Collections.Generic; using System.Linq; using AI.Common; using System.Threading; using AI.Common.Log; using SkiaSharp; using System.Net.Http; using System.Net; using WingInterfaceLibrary.Request.Storage; using WingInterfaceLibrary.Result.AIDiagnosis; using WingInterfaceLibrary.Request.AIDiagnosis; using WingInterfaceLibrary.DTO.Record; using WingInterfaceLibrary.DTO.Comment; using Emgu.CV; using Emgu.CV.CvEnum; using Emgu.CV.Structure; using System.Net.Http.Headers; using WingAIDiagnosisService.Common; namespace WingAIDiagnosisService.Service { /// /// AI诊断服务 /// public partial class AIDiagnosisService : JsonRpcService, IAIDiagnosisService { private EnumPerformance _workerLevel = EnumPerformance.Medium; private int _batchImageSize = 16; private int _sleepTime = 400; private readonly string _tempFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "DiagnosisTemp"); private AIDiagSystem _diagSystem; private AILesionCompareUtils _lesionCompareUtil; private RecognizeCarotidType _recognizeCarotidType = new RecognizeCarotidType(); //识别左右颈是否初始化成功 private static bool _recognizeCarotidTypeCanBeUse = false; static HttpClient _httpClient = new HttpClient(); private IAuthenticationService _authenticationService; private IStorageService _storageService; private readonly string _carotidName = "CarotidPlaqueDetect"; /// /// Init service /// public override void Load(JsonRpcClientPool jsonRpcClientPool) { base.Load(jsonRpcClientPool); _authenticationService = GetProxy(); _storageService = GetProxy(); _workerLevel = (EnumPerformance)ConfigurationManager.GetParammeter("AI", "WorkerLevel").Value; _batchImageSize = ConfigurationManager.GetParammeter("AI", "BatchImageSize").Value; _httpClient.Timeout = TimeSpan.FromMinutes(15); InitAISystem(); //初始化识别左右颈 _recognizeCarotidTypeCanBeUse = _recognizeCarotidType.Initialization(); } private void InitAISystem() { var modeFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Networks"); _diagSystem = new AIDiagSystem(_workerLevel, modeFilePath, EnumInferWorkName.Default, false, true, true); if (_diagSystem != null) { _diagSystem.NotifyError += AIdiagSystem_NotifyError; _diagSystem.NotifyLog += AIdiagSystem_NotifyLog; } _lesionCompareUtil = new AILesionCompareUtils(); } /// /// 查询杏聆荟支持的AI模块 /// /// 查询杏聆荟支持的AI模块请求实体 /// /// false public async Task> FindDiagnosisModulesAsync(TokenRequest request) { try { var moduleNames = AIDiagSystem.GetValidModuleNamesForVclound() ?? new List(); var resultData = moduleNames.Select(x => x.ToString()).ToList(); if (!resultData.Contains(_carotidName)) { resultData.Remove("CarotidArtery"); resultData.Add(_carotidName); } return await Task.FromResult(resultData.Distinct().ToList()); } catch (Exception) { return new List(); } } /// /// 图像诊断 /// /// 图像诊断请求实体 /// 图像诊断结果 /// false public async Task DiagnosisImageAsync(DiagnosisImageRequest request) { try { var localFile = await DownloadAsync(request.FileToken); if (File.Exists(localFile)) { if (_diagSystem == null) { InitAISystem(); } using (var imageData = new VinnoImageData(localFile, OperationMode.Open)) { if (DiagnosisHelper.IsCarotid(imageData)) { if (imageData.ImageCount > DiagnosisHelper.CarotidMinImageCounts) { //颈动脉 var result = await CarotidDiagnosis(imageData); var resultData = new DiagnosisImageResult() { DiagnosisOrgans = new List() { DiagnosisOrganEnum.CarotidArtery }, CarotidResult = result }; return resultData; } } else { //乳腺、肝脏 var results = NormalDiagnosis(imageData); var diagnosisResults = results.Select(x => new AIDiagnosisPerImageModel(x.Key, x.Value)).ToList(); var diagnosisResult = Newtonsoft.Json.JsonConvert.DeserializeObject>(Newtonsoft.Json.JsonConvert.SerializeObject(diagnosisResults)); var resultData = new DiagnosisImageResult() { DiagnosisConclusion = (DiagnosisConclusionEnum)GetDiagnosisConclusion(diagnosisResults), DiagnosisResult = diagnosisResult, DiagnosisOrgans = GetDiagnosisOrgans(diagnosisResult), }; return resultData; } } } } catch (Exception ex) { Logger.WriteLineWarn($"DiagnosisImageAsync err {ex}"); } return new DiagnosisImageResult(); } /// /// 生成AI报告 /// /// 生成AI报告请求实体 /// /// false public async Task DiagnosisReportAsync(DiagnosisReportRequest request) { try { if (request.Organ == DiagnosisOrganEnum.CarotidArtery) { var result = await GetCarotidAIMeasureResult(request); return result; } else { var manager = await CreateDiagnosisManagerAsync(request); var reportPerImages = manager.GetReportResults(); var diagnosisConclusion = GetDiagnosisConclusion(reportPerImages); var diagnosisResult = new List(); foreach (var item in reportPerImages) { var aiFileToken = await UploadFileAsync(item.AILocalImagePath, Path.GetFileName(item.AILocalImagePath)); var perImageResult = Newtonsoft.Json.JsonConvert.DeserializeObject(Newtonsoft.Json.JsonConvert.SerializeObject(item)); perImageResult.RemedicalCode = item.RemedicalCode; perImageResult.DataType = (RemedicalFileDataTypeEnum)item.DataType; perImageResult.Pixel = item.Pixel; perImageResult.AIFileToken = aiFileToken; diagnosisResult.Add(perImageResult); } return new DiagnosisReportResult { DiagnosisConclusion = (DiagnosisConclusionEnum)diagnosisConclusion, DiagnosisResult = diagnosisResult, }; } } catch (Exception ex) { Logger.WriteLineWarn($"AIService DiagnosisReport err, {ex}"); } return new DiagnosisReportResult(); } /// /// 获取颈动脉ai报告数据 /// /// 生成AI报告请求实体 /// private async Task GetCarotidAIMeasureResult(DiagnosisReportRequest request) { var result = new DiagnosisReportResult() { DiagnosisConclusion = DiagnosisConclusionEnum.NoObviousLesion }; var orderedExamDatas = request.RemedicalList.OrderByDescending(m => m.CarotidResult?.CarotidScanType).Where(m => m.CarotidResult?.MeasureImageFiles != null && m.CarotidResult.MeasureImageFiles.Count > 0); if (orderedExamDatas?.Count() > 0) { DiagnosisRemicalDTO leftData = null; //left var leftExamDatas = orderedExamDatas.Where(m => m.CarotidResult.CarotidScanType == CarotidScanTypeEnum.CarotidLeft); if (leftExamDatas.Any()) { foreach (var leftItem in leftExamDatas) { if (string.IsNullOrEmpty(leftItem.CarotidResult.MeasureResult)) { result.DiagnosisConclusion = DiagnosisConclusionEnum.Unrecognized; continue; } //leftItem.CarotidResult.MeasureResult = "{\"IntimaResult\":{\"IsSuccess\":true,\"AntIntima\":{\"IntimaThick\":0.0,\"IsSuccess\":false},\"PostIntima\":{\"IntimaThick\":0.75,\"IsSuccess\":true}},\"IsYImageSuccess\":false,\"PlaqueResult\":{\"PlaquePostion\":0,\"PlaqueCountType\":2,\"PlaqueType\":0,\"PlaqueWidth\":1.75,\"PlaqueHeight\":3.76,\"Stenosis\":10.37,\"IsSuccess\":true}}"; var measureResult = JsonConvert.DeserializeObject(leftItem.CarotidResult.MeasureResult) ?? new CarotidAIMeasureResult(); if (measureResult.PlaqueResult?.PlaqueCountType != Carotid.Utilities.DetectPlaque.PlaqueCountType.NoPlaque) { leftData = leftItem; result.DiagnosisConclusion = DiagnosisConclusionEnum.Other; break; } } if (leftData == null) { leftData = leftExamDatas.First(); } } if (leftData != null) { result.CarotidResult.Add(leftData); } //right float intimaThickStandard = 1.0f; DiagnosisRemicalDTO rightData = null; var rightExamDatas = orderedExamDatas.Where(m => m.CarotidResult.CarotidScanType == CarotidScanTypeEnum.CarotidRight); if (rightExamDatas.Any()) { foreach (var rightItem in rightExamDatas) { if (string.IsNullOrEmpty(rightItem.CarotidResult.MeasureResult)) { result.DiagnosisConclusion = DiagnosisConclusionEnum.Unrecognized; continue; } //rightItem.CarotidResult.MeasureResult = "{\"IntimaResult\":{\"IsSuccess\":true,\"AntIntima\":{\"IntimaThick\":0.0,\"IsSuccess\":false},\"PostIntima\":{\"IntimaThick\":0.75,\"IsSuccess\":true}},\"IsYImageSuccess\":false,\"PlaqueResult\":{\"PlaquePostion\":0,\"PlaqueCountType\":2,\"PlaqueType\":0,\"PlaqueWidth\":1.75,\"PlaqueHeight\":3.76,\"Stenosis\":10.37,\"IsSuccess\":true}}"; var measureResult = JsonConvert.DeserializeObject(rightItem.CarotidResult.MeasureResult) ?? new CarotidAIMeasureResult(); if (measureResult.IntimaResult?.PostIntima?.IntimaThick > intimaThickStandard) { rightData = rightItem; result.DiagnosisConclusion = DiagnosisConclusionEnum.Other; break; } } if (rightData == null) { rightData = rightExamDatas.First(); } } if (rightData != null) { result.CarotidResult.Add(rightData); } Logger.WriteLineInfo($"AIDiagnosisService package carotidAIMeasureResult finished, CarotidLeftRemedicalCode:{leftData?.RemedicalCode}, CarotidLeft:{leftData?.CarotidResult?.MeasureResult}, CarotidRightRemedicalCode:{rightData?.RemedicalCode}, CarotidRight:" + rightData?.CarotidResult?.MeasureResult); } return result; } private async Task CreateDiagnosisManagerAsync(DiagnosisReportRequest request) { var recordResults = new List(); foreach (var remedical in request.RemedicalList) { foreach (var perImage in remedical.DiagnosisResult) { var localFile = await DownloadAsync(remedical.FileToken); if (File.Exists((localFile))) { var diagnosisPerImage = new DiagnosisPerImageModel(); diagnosisPerImage.RemedicalCode = remedical.RemedicalCode; diagnosisPerImage.DataType = (WingAIDiagnosisService.Manage.DataType)remedical.DataType; diagnosisPerImage.LocalVidPath = localFile; diagnosisPerImage.Index = perImage.Index; diagnosisPerImage.PriorityScore = perImage.PriorityScore; var diagnosisResults = Newtonsoft.Json.JsonConvert.DeserializeObject>(Newtonsoft.Json.JsonConvert.SerializeObject(perImage.DiagResultsForEachOrgan)); diagnosisPerImage.DiagResultsForEachOrgan = diagnosisResults; recordResults.Add(diagnosisPerImage); } } } switch (request.Organ) { case DiagnosisOrganEnum.Breast: return new BreastDiagnosis(recordResults, request.Organ); case DiagnosisOrganEnum.Liver: return new LiverDiagnosis(recordResults, request.Organ); default: throw new Exception($"not support organ type:{request.Organ.ToString()}"); } } private async Task CarotidDiagnosis(VinnoImageData imageData) { var resampleInputData = new ResampleInputData(); resampleInputData.SurfaceFilePath = DiagnosisHelper.GetCacheFilePath(DiagnosisHelper.SurfaceFileSuffix); resampleInputData.MdlFilePath = DiagnosisHelper.GetCacheFilePath(DiagnosisHelper.ModelFileSuffix); resampleInputData.MdlZipFilePath = DiagnosisHelper.GetCacheFilePath(DiagnosisHelper.ZipFileSuffix); resampleInputData.BaseAIImagePath = DiagnosisHelper.GetCacheFilePath(DiagnosisHelper.JPGFileSuffix); resampleInputData.PlaqueAIImagePath = DiagnosisHelper.GetCacheFilePath(DiagnosisHelper.JPGFileSuffix); resampleInputData.YShapeAIImagePath = DiagnosisHelper.GetCacheFilePath(DiagnosisHelper.JPGFileSuffix); var resampleResult = TryResample(imageData, resampleInputData); if (resampleResult.ResampleErrorCode == ResampleErrorCode.Success) { var carotidAIImageTokens = new List(); if (resampleResult.CarotidAIMeasureResult.IsYImageSuccess) { var fileUrl = await UploadFileAsync(resampleInputData.YShapeAIImagePath, Path.GetFileName(resampleInputData.YShapeAIImagePath)); if (!string.IsNullOrWhiteSpace(fileUrl)) { carotidAIImageTokens.Add(new CarotidAIImage() { AIImageToken = fileUrl, AIImageType = CarotidAIImageType.YShape }); } File.Delete(resampleInputData.YShapeAIImagePath); } if (resampleResult.CarotidAIMeasureResult.IntimaResult.IsSuccess) { var fileUrl = await UploadFileAsync(resampleInputData.BaseAIImagePath, Path.GetFileName(resampleInputData.BaseAIImagePath)); if (!string.IsNullOrWhiteSpace(fileUrl)) { carotidAIImageTokens.Add(new CarotidAIImage() { AIImageToken = fileUrl, AIImageType = CarotidAIImageType.Base }); } File.Delete(resampleInputData.BaseAIImagePath); } if (resampleResult.CarotidAIMeasureResult.PlaqueResult.IsSuccess && resampleResult.CarotidAIMeasureResult.PlaqueResult.PlaqueCountType != WingAIDiagnosisService.Carotid.Utilities.DetectPlaque.PlaqueCountType.NoPlaque) { var fileUrl = await UploadFileAsync(resampleInputData.PlaqueAIImagePath, Path.GetFileName(resampleInputData.PlaqueAIImagePath)); if (!string.IsNullOrWhiteSpace(fileUrl)) { carotidAIImageTokens.Add(new CarotidAIImage() { AIImageToken = fileUrl, AIImageType = CarotidAIImageType.Plaque }); } File.Delete(resampleInputData.PlaqueAIImagePath); } var surfaceImageList = new List(); long surfaceFileSize=0; var cdnSurfaceFile=""; if (!string.IsNullOrWhiteSpace(resampleInputData.SurfaceFilePath) && File.Exists(resampleInputData.SurfaceFilePath)) { surfaceImageList = await SurfaceFile(resampleInputData.SurfaceFilePath); var surfaceFileTuple = await UploadFileTupleAsync(resampleInputData.SurfaceFilePath, Path.GetFileName(resampleInputData.SurfaceFilePath)); surfaceFileSize=surfaceFileTuple.Item2; File.Delete(resampleInputData.SurfaceFilePath); resampleInputData.SurfaceFilePath = surfaceFileTuple.Item1; cdnSurfaceFile= surfaceFileTuple.Item1.ToUrlToken();//ToCDN } long mdlFileFileSize=0; var cdnMdlFile=""; if (!string.IsNullOrWhiteSpace(resampleInputData.MdlFilePath) && File.Exists(resampleInputData.MdlFilePath)) { var mdlFileTuple = await UploadFileTupleAsync(resampleInputData.MdlFilePath, Path.GetFileName(resampleInputData.MdlFilePath)); mdlFileFileSize=mdlFileTuple.Item2; File.Delete(resampleInputData.MdlFilePath); resampleInputData.MdlFilePath = mdlFileTuple.Item1; cdnMdlFile= mdlFileTuple.Item1.ToUrlToken();//ToCDN } var result = new CarotidResultDTO { CarotidScanType = (CarotidScanTypeEnum)resampleInputData.ScanType, CarotidScanDirection = (CarotidScanDirectionEnum)resampleInputData.CarotidScanDirection, SurfaceFile = resampleInputData.SurfaceFilePath, SurfaceFileSize=surfaceFileSize, CDNSurfaceFile=cdnSurfaceFile, MdlFileSize=mdlFileFileSize, MdlFile = resampleInputData.MdlFilePath, CDNMdlFile=cdnMdlFile, MeasureImageFiles = carotidAIImageTokens.Select(x => new MeasureImageFileDTO { ImageType = (CarotidAIImageTypeEnum)x.AIImageType, ImageFile = x.AIImageToken }).ToList(), MeasureResult = JsonConvert.SerializeObject(resampleResult.CarotidAIMeasureResult), SurfaceImageList = surfaceImageList, }; return result; } return null; } private ResampleResult TryResample(VinnoImageData vinnoImageData, ResampleInputData resampleInputData) { float scanDistance = 7; ResampleResult resampleResult = new ResampleResult(ResampleErrorCode.Fail); var vinnoExtendedData = VinnoCarotidExtendedData.FromBytes(vinnoImageData.ExtendedData); CarotidScanType scanType = CarotidScanType.CarotidLeft; CarotidScanDirection direction = CarotidScanDirection.TopToBottom; if (vinnoExtendedData != null) { // Should be 6~9cm normally. //scanDistance = vinnoExtendedData.ScanDistance; scanType = vinnoExtendedData.CarotidType == CarotidType.Left ? CarotidScanType.CarotidLeft : CarotidScanType.CarotidRight; direction = vinnoExtendedData.CarotidDirection == CarotidDirection.BottomToTop ? CarotidScanDirection.BottomToTop : CarotidScanDirection.TopToBottom; } else { //This is a walkaround : vid's first frame is black image or depth coordinate is not in the right place. var middleCount = vinnoImageData.ImageCount / 2; var vinnoImage = vinnoImageData.GetImage(middleCount); var imageBuffer = vinnoImage.ImageData; if (_recognizeCarotidTypeCanBeUse) { //转成彩色图像 using var img = new Mat(); CvInvoke.Imdecode(imageBuffer, ImreadModes.Color, img); using var image = img.ToImage(); //识别左右颈信息 scanType = _recognizeCarotidType.RecognizeType(image); } } resampleInputData.ScanDistance = scanDistance; resampleInputData.ScanType = scanType; resampleInputData.CarotidScanDirection = direction; resampleResult = ResampleModel.Instance.Resample(vinnoImageData, resampleInputData, _workerLevel); return resampleResult; } /// /// /// /// private async Task> SurfaceFile(string filePath) { var fileUrls = new List(); using (var stream = new FileStream(filePath, FileMode.Open)) { var reader = new Carotid3DStreamReader(stream); var width = reader.ReadInt(); var height = reader.ReadInt(); var depth = reader.ReadInt(); var physicalData = VinnoCarotid3DPhysicalData.FromBytes(reader.ReadBytes()); var imageCount = reader.ReadInt(); var fileName = $"{Guid.NewGuid():N}"; for (var i = 0; i < imageCount; i++) { var readBytes = reader.ReadBytes(); if (readBytes.Any()) { using var img = new Mat(); CvInvoke.Imdecode(readBytes, ImreadModes.Color, img); var buf = new Emgu.CV.Util.VectorOfByte(); using var image = img.ToImage(); CvInvoke.Imencode(".jpg", image, buf, new KeyValuePair(ImwriteFlags.JpegQuality, 80)); var jpgByte = buf.ToArray(); var localPath = Path.Combine(_tempFolder, $"{fileName}_{i + 1}.jpg"); File.WriteAllBytes(localPath, jpgByte); var fileUrl = await UploadFileAsync(localPath, Path.GetFileName(localPath)); fileUrls.Add(fileUrl); File.Delete(localPath); } } } return fileUrls; } private SKBitmap CreateBitmap(VinnoImage vinnoImage) { try { return SKBitmap.Decode(vinnoImage.ImageData); } catch (Exception ex) { Logger.WriteLineError($"Create skbitmap by VinnoImage error:{ex}"); } return null; } private EnumColorType MapTo(SKColorType sKColor) { switch (sKColor) { case SKColorType.Rgba8888: return EnumColorType.Rgba; case SKColorType.Rgb888x: return EnumColorType.Rgba; case SKColorType.Bgra8888: return EnumColorType.Bgra; case SKColorType.Gray8: return EnumColorType.Gray8; } throw new Exception($"AIService not support color type:{sKColor}"); } private void AIdiagSystem_NotifyError(object sender, ErrorEventArgs e) { Logger.WriteLineError("AIdiagSystem_NotifyError:" + e.GetException()); } private void AIdiagSystem_NotifyLog(object sender, LogEventArgs e) { if (e != null && !string.IsNullOrEmpty(e.Msg)) { switch (e.LogType) { case EnumLogType.InfoLog: Logger.WriteLineInfo($"AIdiagSystem_NotifyLog:{e.Msg}"); break; case EnumLogType.ErrorLog: Logger.WriteLineError($"AIdiagSystem_NotifyLog:{e.Msg}"); break; case EnumLogType.WarnLog: Logger.WriteLineWarn($"AIdiagSystem_NotifyLog:{e.Msg}"); break; case EnumLogType.FatalLog: Logger.WriteLineError($"AIdiagSystem_NotifyLog:{e.Msg}"); break; default: Logger.WriteLineInfo(e.Msg); break; } } } private DiagnosisConclusion GetDiagnosisConclusion(List results) where T : AIDiagnosisPerImageModel { var diagnosisConclusions = new List(); foreach (var imageResult in results) { foreach (var diagnosisResult in imageResult.DiagResultsForEachOrgan) { var benignLabels = new List(); var malignantLabels = new List(); if (diagnosisResult.Organ == DiagnosisOrganEnum.Breast) { benignLabels = new List { 1, 2, 3 }; malignantLabels = new List { 4, 5, 6, 7 }; } else if (diagnosisResult.Organ == DiagnosisOrganEnum.Liver) { benignLabels = new List { 1, 2, 3, 5, 6, 7, 8 }; malignantLabels = new List { 4 }; } var labels = diagnosisResult.DetectedObjects.Select(x => x.Label); if (labels.Contains(0)) { diagnosisConclusions.Add(DiagnosisConclusion.NoObviousLesion); } if (labels.Intersect(benignLabels).Any()) { diagnosisConclusions.Add(DiagnosisConclusion.Benign); } if (labels.Intersect(malignantLabels).Any()) { diagnosisConclusions.Add(DiagnosisConclusion.Malignant); } } } var containsBenign = diagnosisConclusions.Contains(DiagnosisConclusion.Benign); var containsMalignant = diagnosisConclusions.Contains(DiagnosisConclusion.Malignant); var containsNoObviousLesion = diagnosisConclusions.Contains(DiagnosisConclusion.NoObviousLesion); if (containsBenign && containsMalignant) { return DiagnosisConclusion.BenignAndMalignant; } else if (containsBenign) { return DiagnosisConclusion.Benign; } else if (containsMalignant) { return DiagnosisConclusion.Malignant; } else if (containsNoObviousLesion) { return DiagnosisConclusion.NoObviousLesion; } else { return DiagnosisConclusion.Unrecognized; } } private List GetDiagnosisOrgans(List results) { var diagnosisOrgans = new List(); foreach (var imageResult in results) { foreach (var diagnosisResult in imageResult.DiagResultsForEachOrgan) { var organName = Enum.GetName(typeof(DiagnosisOrganEnum), (int)diagnosisResult.Organ); if (!string.IsNullOrWhiteSpace(organName) && diagnosisResult.Organ != DiagnosisOrganEnum.Null && diagnosisResult.DetectedObjects?.Any() == true) { diagnosisOrgans.Add((DiagnosisOrganEnum)diagnosisResult.Organ); } } } return diagnosisOrgans.Distinct().ToList(); } private Dictionary NormalDiagnosis(VinnoImageData imageData) { var images = new List(); var results = new Dictionary(); try { var totalCount = imageData.ImageCount; for (var i = 0; i < totalCount; i++) { var image = imageData.GetImage(i); var bitmap = CreateBitmap(image); if (bitmap != null) { images.Add(new RawImage(bitmap.Bytes, bitmap.Width, bitmap.Height, MapTo(bitmap.ColorType))); } } if (images.Count > 0) { var excuteCount = images.Count / _batchImageSize; var remainderCount = images.Count % _batchImageSize; var diagId = _diagSystem.StartEvalutationOfMultipleImageBatches(images.Count); for (var j = 0; j < excuteCount; j++) { var excuteImages = images.GetRange(j * _batchImageSize, _batchImageSize); _diagSystem.PushOneBatchOfImagesAsync(diagId, excuteImages); Thread.Sleep(_sleepTime); } if (remainderCount > 0) { var excuteImages = images.GetRange(excuteCount * _batchImageSize, remainderCount); _diagSystem.PushOneBatchOfImagesAsync(diagId, excuteImages); } results = _diagSystem.GetEvaluationsOfPushedMultipleImageBatches(diagId); } } catch (Exception ex) { Logger.WriteLineWarn($"AIService NormalDiagnosis err, {ex}"); } finally { foreach (var image in images) { image?.Dispose(); } } return results; } /// 下载文件 /// /// private async Task DownloadAsync(string fileUrl) { try { if (string.IsNullOrEmpty(fileUrl)) { return string.Empty; } if (!Directory.Exists(_tempFolder)) { Directory.CreateDirectory(_tempFolder); } var fileName = Path.GetFileName(fileUrl); var tempFile = Path.Combine(_tempFolder, fileName); if (File.Exists(tempFile)) { return tempFile; } long fileSize = 0; using (var request = new HttpRequestMessage()) { request.RequestUri = new Uri(fileUrl); request.Method = HttpMethod.Get; var response = await _httpClient.SendAsync(request); if (response != null && response.StatusCode == HttpStatusCode.OK) { var contentLength = response.Content.Headers.ContentLength; fileSize = contentLength == null ? 0 : contentLength.Value; } } if (fileSize <= 0) { throw new NotSupportedException($"fileSize is {fileSize}"); } byte[] bytes = await _httpClient.GetByteArrayAsync(fileUrl); File.WriteAllBytes(tempFile, bytes); return tempFile; } catch (Exception ex) { Logger.WriteLineWarn($"DiagnosisService download file err, url: {fileUrl}, {ex}"); } finally { //Logger.WriteLineInfo($"download file:{fileUrl}"); } return string.Empty; } /// /// 上传文件 /// /// /// /// private async Task UploadFileAsync(string filePath, string fileName) { var fileToken = ""; using (var fileStream = new FileStream(filePath, FileMode.Open)) { var size = fileStream.Length; byte[] buffer = new byte[fileStream.Length]; fileStream.Read(buffer, 0, buffer.Length); fileToken = await DoUploadFile(fileName, buffer); } return fileToken; } /// /// 上传文件 /// /// /// /// private async Task> UploadFileTupleAsync(string filePath, string fileName) { var fileToken = ""; long size = 0; using (var fileStream = new FileStream(filePath, FileMode.Open)) { size = fileStream.Length; byte[] buffer = new byte[fileStream.Length]; fileStream.Read(buffer, 0, buffer.Length); fileToken = await DoUploadFile(fileName, buffer); } return new Tuple(fileToken, size); } /// /// 上传文件 /// /// /// /// async Task DoUploadFile(string fileName, byte[] fileData) { var requestHeads = new Dictionary(); var defaultToken = await _authenticationService.GetServerDefaultTokenAsync(); var authorizationRet = await _storageService.GetAuthorizationAsync( new FileServiceRequest { Token = defaultToken, FileName = fileName, }); requestHeads.Add("Authorization", authorizationRet.Authorization); var fileUrl = authorizationRet.StorageUrl; Logger.WriteLineInfo($"DoUploadFile fileUrl:{fileUrl}"); using (var request = new HttpRequestMessage()) { var fileExtension = Path.GetExtension(fileName); var mimeType = FileHelper.GetMimeType(fileExtension); var contentType = MediaTypeHeaderValue.Parse(mimeType); using (UploadContent content = new UploadContent(fileData, contentType)) { request.RequestUri = new Uri(fileUrl); request.Method = HttpMethod.Put; request.Content = content; foreach (var head in requestHeads) { request.Headers.TryAddWithoutValidation(head.Key, head.Value); } var result = await ExecuteRequest(request); if (!result) { throw new Exception("Upload file failed!"); } } } return fileUrl; } private UploadFileTypeEnum GetUploadFileType(string fileName) { if (fileName.EndsWith(".vid")) { return UploadFileTypeEnum.VID; } else if (fileName.EndsWith(".jpg")) { return UploadFileTypeEnum.JPG; } else { return UploadFileTypeEnum.MP4; } } /// /// 执行请求 /// /// /// /// public async Task ExecuteRequest(HttpRequestMessage httpRequestMessage) { try { var response = await _httpClient.SendAsync(httpRequestMessage); if (response != null && response.StatusCode == HttpStatusCode.OK) { return true; } return false; } catch (Exception ex) { throw ex; } } } }