12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147 |
- 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;
- using WingInterfaceLibrary.Interface.DBInterface;
- using WingInterfaceLibrary.Request.DBRequest;
- using WingInterfaceLibrary.DTO.DiagnosisResult;
- using WingInterfaceLibrary.Request.RemedicalAISelected;
- using ContourModifyUtils;
- using WingInterfaceLibrary.Request.DBCopy;
- using Newtonsoft.Json.Linq;
- using System.Runtime.CompilerServices;
- using WingInterfaceLibrary.DTO.Common;
- using WingInterfaceLibrary.Request.User;
- using WingInterfaceLibrary.Internal.Interface;
- namespace WingAIDiagnosisService.Service
- {
- /// <summary>
- /// AI诊断服务
- /// </summary>
- 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;
- //识别左右颈是否初始化成功
- private static bool _recognizeCarotidTypeCanBeUse = false;
- static HttpClient _httpClient = new HttpClient();
- private IAuthenticationService _authenticationService;
- private IStorageService _storageService;
- private readonly string _carotidName = "CarotidPlaqueDetect";
- private int _contourInterval = 10;
- private IDiagnosisResultDBService _diagnosisResultDBService;
- private IRemedicalDBService _remedicalDBService;
- private bool _isCarotidOn = true;
- private string _storageDirectory;
- private INotificationService _notificationService;
- /// <summary>
- /// Init service
- /// </summary>
- public override void Load(JsonRpcClientPool jsonRpcClientPool)
- {
- base.Load(jsonRpcClientPool);
- _authenticationService = GetProxy<IAuthenticationService>();
- _storageService = GetProxy<IStorageService>();
- _workerLevel = (EnumPerformance)ConfigurationManager.GetParammeter<IntParameter>("AI", "WorkerLevel").Value;
- _batchImageSize = ConfigurationManager.GetParammeter<IntParameter>("AI", "BatchImageSize").Value;
- _contourInterval = ConfigurationManager.GetParammeter<IntParameter>("AI", "ContourInterval").Value;
- _httpClient.Timeout = TimeSpan.FromMinutes(15);
- _diagnosisResultDBService = GetProxy<IDiagnosisResultDBService>();
- _remedicalDBService = GetProxy<IRemedicalDBService>();
- _notificationService = GetProxy<INotificationService>();
- InitAISystem();
- //初始化识别左右颈
- _isCarotidOn = ConfigurationManager.GetParammeter<BoolParameter>("AI", "IsCarotidOn").Value;
- if (_isCarotidOn)
- {
- _recognizeCarotidType = new RecognizeCarotidType();
- _recognizeCarotidTypeCanBeUse = _recognizeCarotidType.Initialization();
- }
- var storageDisk = EnvironmentConfigManager.GetParammeter<StringParameter>("Storage", "VCSStorageDisk").Value;
- _storageDirectory = Path.Combine(storageDisk, "FlyinsonoStorage");
- var keyPointDistanceThreshold = ConfigurationManager.GetParammeter<IntParameter>("AI", "KeyPointDistanceThreshold").Value;
- var dragStartPointCatchDistanceThreshold = ConfigurationManager.GetParammeter<IntParameter>("AI", "DragStartPointCatchDistanceThreshold").Value;
- ContourModifyHelper.KeyPointDistanceThreshold = keyPointDistanceThreshold;
- ContourModifyHelper.DragStartPointCatchDistanceThreshold = dragStartPointCatchDistanceThreshold;
- }
- private void InitAISystem()
- {
- var modeFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AIDiagnosis", "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();
- }
- /// <summary>
- /// 查询杏聆荟支持的AI模块
- /// </summary>
- /// <param name="request">查询杏聆荟支持的AI模块请求实体</param>
- /// <returns></returns>
- /// <show>false</show>
- public async Task<IList<string>> FindDiagnosisModulesAsync(TokenRequest request)
- {
- try
- {
- var moduleNames = AIDiagSystem.GetValidModuleNamesForVclound() ?? new List<EnumAIModuleNames>();
- 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<string>();
- }
- }
- /// <summary>
- /// 图像诊断
- /// </summary>
- /// <param name="request">图像诊断请求实体</param>
- /// <returns>图像诊断结果</returns>
- /// <show>false</show>
- public async Task<DiagnosisImageResult> DiagnosisImageAsync(DiagnosisImageRequest request)
- {
- try
- {
- var relationCode = request.RelationCode;
- var fileUrl = request.FileToken;
- var localFile = "";
- if (!string.IsNullOrWhiteSpace(request.DiskPath))
- {
- localFile = request.DiskPath;
- }
- else
- {
- localFile = await DownloadAsync(fileUrl);
- }
- if (File.Exists(localFile))
- {
- if (_diagSystem == null)
- {
- InitAISystem();
- }
- var resultData = new DiagnosisImageResult();
- var isCaroid = false;
- var diagnosisPerImages = new List<AIDiagnosisPerImageModel>();
- var results = new Dictionary<int, AIDiagResultPerImg>();
- var organs = new List<DiagnosisOrganEnum>();
- using (var imageData = new VinnoImageData(localFile, OperationMode.Open))
- {
- isCaroid = DiagnosisHelper.IsCarotid(imageData);
- if (isCaroid)
- {
- if (_isCarotidOn)
- {
- //颈动脉
- var result = await CarotidDiagnosis(imageData);
- resultData = new DiagnosisImageResult()
- {
- DiagnosisOrgans = new List<DiagnosisOrganEnum>() { DiagnosisOrganEnum.CarotidArtery },
- CarotidResult = result
- };
- }
- }
- //乳腺、肝脏
- results = NormalDiagnosis(relationCode, fileUrl, imageData);
- //AI实体有很多参数仅支持get,为了方便后续反序列化,db入库前先做个转换
- diagnosisPerImages = results.Select(x => new AIDiagnosisPerImageModel(x.Key, x.Value, 1)).ToList();
- diagnosisPerImages = GetAIDiagnosisPerImages(diagnosisPerImages, imageData, isCaroid);
- if (diagnosisPerImages == null || !diagnosisPerImages.Any())
- {
- return new DiagnosisImageResult
- {
- DiagnosisConclusion = DiagnosisConclusionEnum.Unrecognized,
- DiagnosisResult = null,
- DiagnosisOrgans = new List<DiagnosisOrganEnum>(),
- };
- }
- organs = GetDiagnosisOrgans(diagnosisPerImages);
- await AddDiagnosisResultInfosAsync(relationCode, fileUrl, diagnosisPerImages);
- //轮廓线分隔处理
- diagnosisPerImages = results.Select(x => new AIDiagnosisPerImageModel(x.Key, x.Value, _contourInterval)).ToList();
- diagnosisPerImages = GetAIDiagnosisPerImages(diagnosisPerImages, imageData, isCaroid);
- }
- var diagnosisResult = JsonConvert.DeserializeObject<List<AIDiagnosisPerImageDTO>>(JsonConvert.SerializeObject(diagnosisPerImages));
- resultData.DiagnosisConclusion = (DiagnosisConclusionEnum)GetDiagnosisConclusion(diagnosisPerImages);
- resultData.DiagnosisResult = diagnosisResult;
- resultData.DiagnosisOrgans.AddRange(organs);
- return resultData;
- }
- }
- catch (Exception ex)
- {
- Logger.WriteLineWarn($"DiagnosisImageAsync err {ex}");
- }
- return new DiagnosisImageResult();
- }
- private List<AIDiagnosisPerImageModel> GetAIDiagnosisPerImages(List<AIDiagnosisPerImageModel> diagnosisPerImages, VinnoImageData imageData, bool isCaroid)
- {
- if (isCaroid && diagnosisPerImages.Count == 1)
- {
- foreach (var perImage in diagnosisPerImages)
- {
- if (perImage.DiagResultsForEachOrgan.All(x => x.Organ != DiagnosisOrganEnum.CarotidArtery))
- {
- var orgs = new List<WingAIDiagnosisService.Manage.AIDiagnosisResultPerOrgan>();
- foreach (var org in perImage.DiagResultsForEachOrgan)
- {
- org.Organ = DiagnosisOrganEnum.CarotidArtery;
- foreach (var detectedObject in org.DetectedObjects)
- {
- detectedObject.Label = 0;
- detectedObject.Contour = new List<Manage.AIDiagnosisPoint2D>();
- detectedObject.Contours = new List<Manage.AIDiagnosisPoint2D>();
- detectedObject.Descriptions = new List<Manage.AIDiagnosisDescription>();
- }
- orgs.Add(org);
- }
- perImage.DiagResultsForEachOrgan = orgs;
- }
- }
- }
- foreach (var perImage in diagnosisPerImages)
- {
- var orgs = new List<WingAIDiagnosisService.Manage.AIDiagnosisResultPerOrgan>();
- foreach (var org in perImage.DiagResultsForEachOrgan)
- {
- if (org.Organ == DiagnosisOrganEnum.CarotidArtery)
- {
- var physicalPerPixel = BaseDiagnosis.GetPhysicalPerPixel(imageData, perImage.Index, true);
- var info = GetReportDetectedObject(perImage.DiagResultsForEachOrgan, physicalPerPixel * 10);
- if (info.Item4 < 1.4)
- {
- foreach (var a in org.DetectedObjects)
- {
- a.Label = 0;
- a.Contour = new List<Manage.AIDiagnosisPoint2D>();
- a.Contours = new List<Manage.AIDiagnosisPoint2D>();
- a.Descriptions = new List<Manage.AIDiagnosisDescription>();
- }
- }
- orgs.Add(org);
- }
- else
- {
- orgs.Add(org);
- }
- }
- perImage.DiagResultsForEachOrgan = orgs;
- }
- var organs = GetDiagnosisOrgans(diagnosisPerImages);
- if (organs.Contains(DiagnosisOrganEnum.Breast))
- {
- var breastCount = diagnosisPerImages.Where(a => a.PriorityScore > 0 && a.DiagResultsForEachOrgan != null && a.DiagResultsForEachOrgan.Any(x => x.Organ == DiagnosisOrganEnum.Breast)).Count();
- var totalCount = diagnosisPerImages.Count;
- var breastRate = breastCount * 1.0 / totalCount * 1.0;
- if (organs.All(x => x == DiagnosisOrganEnum.Breast))
- {
- if (breastRate <= 1 / 3.0)
- {
- return new List<AIDiagnosisPerImageModel>();
- }
- }
- else
- {
- if (breastRate <= 1 / 3.0)
- {
- foreach (var item in diagnosisPerImages)
- {
- item.DiagResultsForEachOrgan = item.DiagResultsForEachOrgan?.Where(x => x.Organ != DiagnosisOrganEnum.Breast)?.ToList() ?? new List<Manage.AIDiagnosisResultPerOrgan>();
- }
- }
- }
- }
- if (isCaroid)
- {
- var carotidCount = diagnosisPerImages.Count(x => x.DiagResultsForEachOrgan.Any(x => x.Organ == DiagnosisOrganEnum.CarotidArtery));
- var throidCount = diagnosisPerImages.Count(x => x.DiagResultsForEachOrgan.Any(x => x.Organ == DiagnosisOrganEnum.Thyroid));
- if (carotidCount > throidCount)
- {
- foreach (var item in diagnosisPerImages)
- {
- item.DiagResultsForEachOrgan = item.DiagResultsForEachOrgan?.Where(x => x.Organ == DiagnosisOrganEnum.CarotidArtery)?.ToList() ?? new List<Manage.AIDiagnosisResultPerOrgan>();
- }
- }
- else
- {
- foreach (var item in diagnosisPerImages)
- {
- item.DiagResultsForEachOrgan = item.DiagResultsForEachOrgan?.Where(x => x.Organ == DiagnosisOrganEnum.Thyroid)?.ToList() ?? new List<Manage.AIDiagnosisResultPerOrgan>();
- }
- }
- }
- return diagnosisPerImages;
- }
- private class TempAIResult
- {
- public int Index { get; set; }
- public AIDiagnosisPerImageModel ImageDiagResult { get; set; }
- }
- private class Description : AI.Common.IDescription
- {
- public EnumDescriptionType Type { get; set; }
- // 其他必要的实现,根据您的接口定义
- }
- private class DescriptionConverter : JsonConverter
- {
- public override bool CanConvert(Type objectType)
- {
- return (objectType == typeof(AI.Common.IDescription));
- }
- public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
- {
- throw new NotImplementedException();
- }
- public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
- {
- var jsonObject = JObject.Load(reader);
- var description = new Description();
- serializer.Populate(jsonObject.CreateReader(), description);
- return description;
- }
- }
- public async Task<DiagnosisImageResult> GetDiagnosisImageResultByAIResultAsync(GetDiagnosisImageResultByAIResultRequest request)
- {
- try
- {
- var aiResult = request.AiResult;
- var relationCode = request.RelationCode;
- var fileUrl = request.FileUrl;
- var createTime = request.CreateTime;
- var upateTime = request.UpdateTime;
- //乳腺、肝脏
- // var settings = new JsonSerializerSettings
- // {
- // Converters = new List<JsonConverter> { new DescriptionConverter() }
- // };
- var aiDiagResultPerImgList = JsonConvert.DeserializeObject<List<TempAIResult>>(aiResult);
- foreach (var item in aiDiagResultPerImgList)
- {
- item.ImageDiagResult.Index = item.Index;
- }
- var diagnosisPerImages = aiDiagResultPerImgList.Select(x => x.ImageDiagResult)?.ToList() ?? new List<AIDiagnosisPerImageModel>();
- foreach (var perImage in diagnosisPerImages)
- {
- foreach (var perOrgan in perImage.DiagResultsForEachOrgan)
- {
- var detectedObjects = new List<WingAIDiagnosisService.Manage.AIDetectedObject>();
- foreach (var perDetectedObject in perOrgan.DetectedObjects)
- {
- if (perDetectedObject.Descriptions != null && perDetectedObject.Descriptions.Any())
- {
- foreach (var item in perDetectedObject.Descriptions)
- {
- item.Type = item.DescriptionType;
- item.Value = item.DescriptionValue;
- }
- }
- detectedObjects.Add(perDetectedObject);
- }
- perOrgan.DetectedObjects = detectedObjects;
- }
- }
- var organs = GetDiagnosisOrgans(diagnosisPerImages);
- await AddDiagnosisResultInfosAsync(relationCode, fileUrl, diagnosisPerImages, createTime, upateTime, false);
- //轮廓线分隔处理
- foreach (var perImage in diagnosisPerImages)
- {
- foreach (var perOrgan in perImage.DiagResultsForEachOrgan)
- {
- var organContours = new List<WingAIDiagnosisService.Manage.AIDiagnosisPoint2D>();
- if (perOrgan.OrganContour != null && perOrgan.OrganContour.Count > 0)
- {
- var coutours = perOrgan.OrganContour;
- if (coutours != null && coutours.Count > 0)
- {
- for (var i = 0; i < coutours.Count; i++)
- {
- if (i % _contourInterval == 0)
- {
- organContours.Add(coutours[i]);
- }
- }
- }
- }
- perOrgan.OrganContours = organContours;
- perOrgan.OrganContour = new List<Manage.AIDiagnosisPoint2D>();
- var detectedObjects = new List<WingAIDiagnosisService.Manage.AIDetectedObject>();
- foreach (var perDetectedObject in perOrgan.DetectedObjects)
- {
- var contours = new List<WingAIDiagnosisService.Manage.AIDiagnosisPoint2D>();
- if (perDetectedObject.Contour != null && perDetectedObject.Contour.Count > 0)
- {
- var coutours = perDetectedObject.Contour;
- if (coutours != null && coutours.Count > 0)
- {
- for (var i = 0; i < coutours.Count; i++)
- {
- if (i % _contourInterval == 0)
- {
- contours.Add(coutours[i]);
- }
- }
- }
- }
- perDetectedObject.Contours = contours;
- perDetectedObject.Contour = new List<Manage.AIDiagnosisPoint2D>();
- detectedObjects.Add(perDetectedObject);
- }
- perOrgan.DetectedObjects = detectedObjects;
- }
- }
- var diagnosisResult = Newtonsoft.Json.JsonConvert.DeserializeObject<List<AIDiagnosisPerImageDTO>>(Newtonsoft.Json.JsonConvert.SerializeObject(diagnosisPerImages));
- var resultData = new DiagnosisImageResult()
- {
- DiagnosisConclusion = (DiagnosisConclusionEnum)GetDiagnosisConclusion(diagnosisPerImages),
- DiagnosisResult = diagnosisResult,
- DiagnosisOrgans = organs,
- };
- return resultData;
- }
- catch (Exception ex)
- {
- Logger.WriteLineWarn("GetDiagnosisImageResultByAIResultAsync" + ex);
- return null;
- }
- }
- public async Task<CarotidResultDTO> GetCarotidResultAsync(GetCarotidResultRequest request)
- {
- try
- {
- var surfaceToken = request.SurfaceToken;
- var mdlToken = request.MdlToken;
- CarotidScanTypeEnum carotidScanType = request.CarotidScanType;
- CarotidScanDirectionEnum carotidScanDirection = request.CarotidScanDirection;
- var measureImageFiles = request.MeasureImageFiles;
- var measureResult = request.MeasureResult;
- var surfaceImageList = new List<string>();
- if (MatchCurrentStorage(surfaceToken))
- {
- surfaceImageList = await SurfaceFileByUrl(surfaceToken);
- }
- var result = new CarotidResultDTO
- {
- CarotidScanType = carotidScanType,
- CarotidScanDirection = carotidScanDirection,
- SurfaceFile = surfaceToken,
- SurfaceFileSize = 0,
- CDNSurfaceFile = surfaceToken,//源站地址
- MdlFileSize = 0,
- MdlFile = mdlToken,//源站地址
- CDNMdlFile = mdlToken,
- MeasureImageFiles = measureImageFiles,
- MeasureResult = measureResult,
- SurfaceImageList = surfaceImageList,
- };
- return result;
- }
- catch (Exception ex)
- {
- Logger.WriteLineWarn("GetCarotidResultAsync" + ex);
- return null;
- }
- }
- /// <summary>
- /// 根据颈动脉体数据生成3D 6面图像集合
- /// </summary>
- /// <param name="request"></param>
- /// <returns></returns>
- /// <show>false</show>
- public async Task<CreateCarotidSurfaceImagesResult> CreateCarotidSurfaceImagesAsync(CreateCarotidSurfaceImagesRequest request)
- {
- var surfaceImages = new List<string>();
- try
- {
- var surfaceFileUrl = request.SurfaceFileUrl;
- var result = await SurfaceFileByUrl(surfaceFileUrl);
- if (result != null && result.Any())
- {
- surfaceImages = result;
- }
- }
- catch (Exception ex)
- {
- Logger.WriteLineWarn($"AIDiagnosisService CreateCarotidSurfaceImagesAsync error, ex:{ex}");
- }
- return new CreateCarotidSurfaceImagesResult { SurfaceImages = surfaceImages };
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="baseUrl"></param>
- private async Task<List<string>> SurfaceFileByUrl(string baseUrl)
- {
- var fileUrls = new List<string>();
- var localPath = await DownloadAsync(baseUrl);
- if (!string.IsNullOrWhiteSpace(localPath))
- {
- fileUrls = await SurfaceFile(localPath);
- }
- return fileUrls;
- }
- /// <summary>
- /// 生成AI报告
- /// </summary>
- /// <param name="request">生成AI报告请求实体</param>
- /// <returns></returns>
- /// <show>false</show>
- public async Task<DiagnosisReportResult> DiagnosisReportAsync(DiagnosisReportRequest request)
- {
- var disgnosisReportResult = new DiagnosisReportResult();
- try
- {
- var is3DCarotid = false;
- if (request.Organ == DiagnosisOrganEnum.CarotidArtery && is3DCarotid)
- {
- var result = await GetCarotidAIMeasureResult(request);
- return result;
- }
- else
- {
- var reportPerImages = new List<DiagnosisPerImageModel>();
- if (request.Organ == DiagnosisOrganEnum.CarotidArtery)
- {
- var leftRemedicals = request.RemedicalList.Where(x => x.CarotidResult.CarotidScanType == CarotidScanTypeEnum.CarotidLeft)?.ToList() ?? new List<DiagnosisRemicalDTO>();
- var leftRemedicalCode = string.Empty;
- double leftPhysicalPerPixel = 0;
- if (leftRemedicals.Any())
- {
- var managerLeft = await CreateDiagnosisManagerAsync(new DiagnosisReportRequest { Organ = request.Organ, RemedicalList = leftRemedicals });
- var perImages = managerLeft.GetReportResults();
- leftRemedicalCode = perImages.FirstOrDefault()?.RemedicalCode;
- leftPhysicalPerPixel = perImages.FirstOrDefault()?.Pixel ?? 0;
- reportPerImages.AddRange(perImages);
- }
- disgnosisReportResult.CarotidItems.AddRange(GetCarotidLeftReportItems(leftRemedicals.FirstOrDefault(x => x.RemedicalCode == leftRemedicalCode), leftPhysicalPerPixel));
- var rightRemedicals = request.RemedicalList.Where(x => x.CarotidResult.CarotidScanType == CarotidScanTypeEnum.CarotidRight)?.ToList() ?? new List<DiagnosisRemicalDTO>();
- var rightRemedicalCode = string.Empty;
- double rightPhysicalPerPixel = 0;
- if (rightRemedicals.Any())
- {
- var managerRight = await CreateDiagnosisManagerAsync(new DiagnosisReportRequest { Organ = request.Organ, RemedicalList = rightRemedicals });
- var perImages = managerRight.GetReportResults();
- rightRemedicalCode = perImages.FirstOrDefault()?.RemedicalCode;
- rightPhysicalPerPixel = perImages.FirstOrDefault()?.Pixel ?? 0;
- reportPerImages.AddRange(perImages);
- }
- disgnosisReportResult.CarotidItems.AddRange(GetCarotidRightReportItems(rightRemedicals.FirstOrDefault(x => x.RemedicalCode == rightRemedicalCode), rightPhysicalPerPixel));
- }
- else
- {
- var manager = await CreateDiagnosisManagerAsync(request);
- reportPerImages = manager.GetReportResults();
- }
- var diagnosisConclusion = GetDiagnosisConclusion(reportPerImages);
- var diagnosisOrgans = GetDiagnosisOrgans(reportPerImages);
- var diagnosisResult = new List<DiagnosisPerImageDTO>();
- foreach (var item in reportPerImages)
- {
- var aiFileToken = await UploadFileAsync(item.AILocalImagePath, Path.GetFileName(item.AILocalImagePath));
- var previewPath = Path.Combine(_tempFolder, $"{Guid.NewGuid():N}.jpg");
- CreateThumbnailFile(item.AILocalImagePath, 100, 30, previewPath);
- var previewUrl = await UploadFileAsync(previewPath, Path.GetFileName(previewPath));
- var perImageJson = Newtonsoft.Json.JsonConvert.SerializeObject(item);
- var perImageResult = Newtonsoft.Json.JsonConvert.DeserializeObject<DiagnosisPerImageDTO>(perImageJson);
- perImageResult.RemedicalCode = item.RemedicalCode;
- perImageResult.DataType = (RemedicalFileDataTypeEnum)item.DataType;
- perImageResult.Pixel = item.Pixel;
- perImageResult.AIFileToken = aiFileToken;
- perImageResult.AIPreviewFileToken = previewUrl;
- perImageResult.PerImageJson = perImageJson;
- var conclusion = GetDiagnosisConclusion(new List<DiagnosisPerImageModel> { item });
- var organs = GetDiagnosisOrgans(new List<DiagnosisPerImageModel> { item });
- perImageResult.DiagnosisConclusion = (DiagnosisConclusionEnum)conclusion;
- perImageResult.DiagnosisOrgans = organs;
- diagnosisResult.Add(perImageResult);
- }
- disgnosisReportResult.DiagnosisConclusion = (DiagnosisConclusionEnum)diagnosisConclusion;
- disgnosisReportResult.DiagnosisResult = diagnosisResult;
- }
- }
- catch (Exception ex)
- {
- Logger.WriteLineWarn($"AIService DiagnosisReport err, {ex}");
- }
- return disgnosisReportResult;
- }
- private List<DataItemDTO> GetCarotidLeftReportItems(DiagnosisRemicalDTO leftData, double physicalPerPixel)
- {
- var reportItems = new List<DataItemDTO>();
- if (leftData == null)
- {
- reportItems.Add(new DataItemDTO { Key = "bd170b6a-e052-42f0-a778-4ec85138c1c6;33c0aaf8-e48e-4474-af68-b47d2378073f;LeftConclusion", Value = "" });
- reportItems.Add(new DataItemDTO { Key = "d2449fa2-70e7-45d1-80e3-f69c62652186;98d1e829-b0ee-440d-ae3b-02ff74521357;LeftPlaqueThick", Value = "" });
- reportItems.Add(new DataItemDTO { Key = "6f57bb90-6492-421e-ad3e-6c684b7f7452;6e36fa47-edb2-4ed8-8521-ddb9e1fa5536;LeftPlaquePosition", Value = "" });
- reportItems.Add(new DataItemDTO { Key = "ccef71cd-1c52-4614-a54f-d6d58cb8c586;d440eb6e-2630-4787-8700-486d097ba9f1;LeftPlaqueEcho", Value = "" });
- reportItems.Add(new DataItemDTO { Key = "9a6f96bb-b81e-407d-bc84-9d9815e96696;fe948295-b065-46b9-ab25-fe80144d7bff;LeftCarotidAD", Value = "" });
- reportItems.Add(new DataItemDTO { Key = "e3610e58-79c4-4e18-94c9-8928583b9dab;e6da9399-b849-4017-a3b8-e3212f55c4a4;LeftStenosisRate", Value = "" });
- return reportItems;
- }
- var carotidResultInfos = GetCarotidResultInfos(leftData);
- if (carotidResultInfos.Any(x => x.DetectedObjects.Any(x => x.Label == 1)))
- {
- //有斑块
- reportItems.Add(new DataItemDTO { Key = "bd170b6a-e052-42f0-a778-4ec85138c1c6;33c0aaf8-e48e-4474-af68-b47d2378073f;LeftConclusion", Value = FormatterPlaceholder2($"OnePlaque") });
- var info = GetReportDetectedObject(carotidResultInfos, physicalPerPixel * 10);
- var reportDetectedObject = info.Item1;
- reportItems.Add(new DataItemDTO { Key = "d2449fa2-70e7-45d1-80e3-f69c62652186;98d1e829-b0ee-440d-ae3b-02ff74521357;LeftPlaqueThick", Value = info.Item3.ToString() });
- var locationItem = GetDescription(reportDetectedObject, DiagnosisDescriptionEnum.QlaqueLocation);
- if (locationItem != null)
- {
- reportItems.Add(new DataItemDTO { Key = "6f57bb90-6492-421e-ad3e-6c684b7f7452;6e36fa47-edb2-4ed8-8521-ddb9e1fa5536;LeftPlaquePosition", Value = FormatterPlaceholder2($"{locationItem.Value}") });
- }
- var echoItem = GetDescription(reportDetectedObject, DiagnosisDescriptionEnum.QlaqueEchoPattern);
- if (echoItem != null)
- {
- reportItems.Add(new DataItemDTO { Key = "ccef71cd-1c52-4614-a54f-d6d58cb8c586;d440eb6e-2630-4787-8700-486d097ba9f1;LeftPlaqueEcho", Value = FormatterPlaceholder2($"{echoItem.Value}") });
- }
- var rateOfStenosis = GetDescription(reportDetectedObject, DiagnosisDescriptionEnum.CarotidRateOfStenosis);
- if (rateOfStenosis != null)
- {
- var rateOfStenosisValue = string.Empty;
- var rate = rateOfStenosis.Value.ToFloat() * 100;
- if (rate < 30)
- {
- rateOfStenosisValue = "Normal";
- }
- else if (rate >= 30 && rate < 50)
- {
- rateOfStenosisValue = "Mild";
- }
- else if (rate >= 50 && rate < 70)
- {
- rateOfStenosisValue = "Moderate";
- }
- else if (rate >= 70 && rate < 100)
- {
- rateOfStenosisValue = "Severe";
- }
- else
- {
- rateOfStenosisValue = "Blockage";
- }
- reportItems.Add(new DataItemDTO { Key = "e3610e58-79c4-4e18-94c9-8928583b9dab;e6da9399-b849-4017-a3b8-e3212f55c4a4;LeftStenosisRate", Value = FormatterPlaceholder2(rateOfStenosisValue) });
- }
- var innerDiameter = GetDescription(reportDetectedObject, DiagnosisDescriptionEnum.CarotidInnerDiameter);
- if (innerDiameter != null && !string.IsNullOrWhiteSpace(innerDiameter.Value))
- {
- var diagnosisMeasuringLine = JsonConvert.DeserializeObject<AIDiagnosisMeasuringLine>(innerDiameter.Value);
- var measuringLineLengthInPixel = Math.Round(diagnosisMeasuringLine.MeasuringLineLengthInPixel * physicalPerPixel * 10, 2);
- reportItems.Add(new DataItemDTO { Key = "9a6f96bb-b81e-407d-bc84-9d9815e96696;fe948295-b065-46b9-ab25-fe80144d7bff;LeftCarotidAD", Value = measuringLineLengthInPixel.ToString() });
- }
- }
- else
- {
- // reportItems.Add(new DataItemDTO { Key = "bd170b6a-e052-42f0-a778-4ec85138c1c6;33c0aaf8-e48e-4474-af68-b47d2378073f;LeftConclusion", Value = FormatterPlaceholder2($"NoPlaque2") });
- reportItems.Add(new DataItemDTO { Key = "bd170b6a-e052-42f0-a778-4ec85138c1c6;33c0aaf8-e48e-4474-af68-b47d2378073f;LeftConclusion", Value = "" });
- reportItems.Add(new DataItemDTO { Key = "d2449fa2-70e7-45d1-80e3-f69c62652186;98d1e829-b0ee-440d-ae3b-02ff74521357;LeftPlaqueThick", Value = "" });
- reportItems.Add(new DataItemDTO { Key = "6f57bb90-6492-421e-ad3e-6c684b7f7452;6e36fa47-edb2-4ed8-8521-ddb9e1fa5536;LeftPlaquePosition", Value = "" });
- reportItems.Add(new DataItemDTO { Key = "ccef71cd-1c52-4614-a54f-d6d58cb8c586;d440eb6e-2630-4787-8700-486d097ba9f1;LeftPlaqueEcho", Value = "" });
- reportItems.Add(new DataItemDTO { Key = "9a6f96bb-b81e-407d-bc84-9d9815e96696;fe948295-b065-46b9-ab25-fe80144d7bff;LeftCarotidAD", Value = "" });
- reportItems.Add(new DataItemDTO { Key = "e3610e58-79c4-4e18-94c9-8928583b9dab;e6da9399-b849-4017-a3b8-e3212f55c4a4;LeftStenosisRate", Value = "" });
- }
- return reportItems;
- }
- private List<DataItemDTO> GetCarotidRightReportItems(DiagnosisRemicalDTO rightData, double physicalPerPixel)
- {
- var reportItems = new List<DataItemDTO>();
- if (rightData == null)
- {
- reportItems.Add(new DataItemDTO { Key = "ec4c775e-601c-48cc-a1a9-f39c8629e3f7;9918912e-b702-4a2b-8b4f-61dcfb846be3;RightConclusion", Value = "" });
- reportItems.Add(new DataItemDTO { Key = "8e467ffb-da00-4d34-9aac-34e4e8f91844;46166cb6-ad3a-4ca2-821e-bd872137fa64;RightPlaqueThick", Value = "" });
- reportItems.Add(new DataItemDTO { Key = "1153870e-10c8-4674-99bf-108937db1060;053091d2-8ea0-4fcb-a222-00b46f60d12f;RightPlaquePosition", Value = "" });
- reportItems.Add(new DataItemDTO { Key = "c82e8655-169f-42be-ac99-5e7a56329924;e77f550d-37f3-492a-98dd-a981535383a5;RightPlaqueEcho", Value = "" });
- reportItems.Add(new DataItemDTO { Key = "b0092e8a-25ba-4690-b70f-e3525e6aaa39;2e742ddc-fa90-47bb-ac24-664238773b30;RightStenosisRate", Value = "" });
- reportItems.Add(new DataItemDTO { Key = "8c7543e9-95f2-4862-b2aa-4c4cb032948e;9f8e95ee-a262-41c2-9d4b-efbc7974b397;RightCarotidAD", Value = "" });
- return reportItems;
- }
- var carotidResultInfos = GetCarotidResultInfos(rightData);
- if (carotidResultInfos.Any(x => x.DetectedObjects.Any(x => x.Label == 1)))
- {
- //有斑块
- reportItems.Add(new DataItemDTO { Key = "ec4c775e-601c-48cc-a1a9-f39c8629e3f7;9918912e-b702-4a2b-8b4f-61dcfb846be3;RightConclusion", Value = FormatterPlaceholder2($"OnePlaque") });
- var info = GetReportDetectedObject(carotidResultInfos, physicalPerPixel * 10);
- var reportDetectedObject = info.Item1;
- reportItems.Add(new DataItemDTO { Key = "8e467ffb-da00-4d34-9aac-34e4e8f91844;46166cb6-ad3a-4ca2-821e-bd872137fa64;RightPlaqueThick", Value = info.Item3.ToString() });
- var locationItem = GetDescription(reportDetectedObject, DiagnosisDescriptionEnum.QlaqueLocation);
- if (locationItem != null)
- {
- reportItems.Add(new DataItemDTO { Key = "1153870e-10c8-4674-99bf-108937db1060;053091d2-8ea0-4fcb-a222-00b46f60d12f;RightPlaquePosition", Value = FormatterPlaceholder2($"{locationItem.Value}") });
- }
- var echoItem = GetDescription(reportDetectedObject, DiagnosisDescriptionEnum.QlaqueEchoPattern);
- if (echoItem != null)
- {
- reportItems.Add(new DataItemDTO { Key = "c82e8655-169f-42be-ac99-5e7a56329924;e77f550d-37f3-492a-98dd-a981535383a5;RightPlaqueEcho", Value = FormatterPlaceholder2($"{echoItem.Value}") });
- }
- var rateOfStenosis = GetDescription(reportDetectedObject, DiagnosisDescriptionEnum.CarotidRateOfStenosis);
- if (rateOfStenosis != null)
- {
- var rateOfStenosisValue = string.Empty;
- var rate = rateOfStenosis.Value.ToFloat() * 100;
- if (rate < 30)
- {
- rateOfStenosisValue = "Normal";
- }
- else if (rate >= 30 && rate < 50)
- {
- rateOfStenosisValue = "Mild";
- }
- else if (rate >= 50 && rate < 70)
- {
- rateOfStenosisValue = "Moderate";
- }
- else if (rate >= 70 && rate < 100)
- {
- rateOfStenosisValue = "Severe";
- }
- else
- {
- rateOfStenosisValue = "Blockage";
- }
- reportItems.Add(new DataItemDTO { Key = "b0092e8a-25ba-4690-b70f-e3525e6aaa39;2e742ddc-fa90-47bb-ac24-664238773b30;RightStenosisRate", Value = FormatterPlaceholder2(rateOfStenosisValue) });
- }
- var innerDiameter = GetDescription(reportDetectedObject, DiagnosisDescriptionEnum.CarotidInnerDiameter);
- if (innerDiameter != null && !string.IsNullOrWhiteSpace(innerDiameter.Value))
- {
- var diagnosisMeasuringLine = JsonConvert.DeserializeObject<AIDiagnosisMeasuringLine>(innerDiameter.Value);
- var measuringLineLengthInPixel = Math.Round(diagnosisMeasuringLine.MeasuringLineLengthInPixel * physicalPerPixel * 10, 2);
- reportItems.Add(new DataItemDTO { Key = "8c7543e9-95f2-4862-b2aa-4c4cb032948e;9f8e95ee-a262-41c2-9d4b-efbc7974b397;RightCarotidAD", Value = measuringLineLengthInPixel.ToString() });
- }
- }
- else
- {
- // reportItems.Add(new DataItemDTO { Key = "ec4c775e-601c-48cc-a1a9-f39c8629e3f7;9918912e-b702-4a2b-8b4f-61dcfb846be3;RightConclusion", Value = FormatterPlaceholder2($"NoPlaque2") });
- reportItems.Add(new DataItemDTO { Key = "ec4c775e-601c-48cc-a1a9-f39c8629e3f7;9918912e-b702-4a2b-8b4f-61dcfb846be3;RightConclusion", Value = "" });
- reportItems.Add(new DataItemDTO { Key = "8e467ffb-da00-4d34-9aac-34e4e8f91844;46166cb6-ad3a-4ca2-821e-bd872137fa64;RightPlaqueThick", Value = "" });
- reportItems.Add(new DataItemDTO { Key = "1153870e-10c8-4674-99bf-108937db1060;053091d2-8ea0-4fcb-a222-00b46f60d12f;RightPlaquePosition", Value = "" });
- reportItems.Add(new DataItemDTO { Key = "c82e8655-169f-42be-ac99-5e7a56329924;e77f550d-37f3-492a-98dd-a981535383a5;RightPlaqueEcho", Value = "" });
- reportItems.Add(new DataItemDTO { Key = "b0092e8a-25ba-4690-b70f-e3525e6aaa39;2e742ddc-fa90-47bb-ac24-664238773b30;RightStenosisRate", Value = "" });
- reportItems.Add(new DataItemDTO { Key = "8c7543e9-95f2-4862-b2aa-4c4cb032948e;9f8e95ee-a262-41c2-9d4b-efbc7974b397;RightCarotidAD", Value = "" });
- }
- return reportItems;
- }
- /// <summary>
- /// 查询AI诊断结论
- /// </summary>
- /// <param name="request">查询AI诊断结论请求实体</param>
- /// <returns></returns>
- /// <show>false</show>
- public async Task<GetDiagnosisConclusionResult> GetDiagnosisConclusionAsync(GetDiagnosisConclusionRequest request)
- {
- var preImage = Newtonsoft.Json.JsonConvert.DeserializeObject<DiagnosisPerImageModel>(request.PerImageJson);
- var conclusion = GetDiagnosisConclusion(new List<DiagnosisPerImageModel> { preImage });
- var organs = GetDiagnosisOrgans(new List<DiagnosisPerImageModel> { preImage });
- var resultData = new GetDiagnosisConclusionResult
- {
- DiagnosisConclusion = (DiagnosisConclusionEnum)conclusion,
- DiagnosisOrgans = organs,
- };
- return await Task.FromResult(resultData);
- }
- /// <summary>
- /// 查询AI相关枚举集合
- /// </summary>
- /// <param name="request">查询AI相关枚举集合请求实体</param>
- /// <returns>AI相关枚举集合</returns>
- /// <value></value>
- /// <errorCodes></errorCodes>
- public async Task<GetDiagnosisEnumItemsResult> GetDiagnosisEnumItemsAsync(GetDiagnosisEnumItemsRequest request)
- {
- var diagnosisItems = new List<EnumItemDTO>();
- //病灶
- diagnosisItems.Add(GetEnumItem(typeof(DiagnosisBreastLabelEnum), "Breast", new List<string> { "BIRads1" }));
- diagnosisItems.Add(GetEnumItem(typeof(DiagnosisLiverLabelEnum), "Liver", new List<string> { "BIRads1" }));
- diagnosisItems.Add(GetEnumItem(typeof(AIThyroidLabelEnum), "Thyroid", new List<string> { "TIRADS0" }));
- //病灶特性描述
- diagnosisItems.Add(GetEnumItem(typeof(EnumDesShapeValue)));
- diagnosisItems.Add(GetEnumItem(typeof(EnumDesOrientationValue)));
- diagnosisItems.Add(GetEnumItem(typeof(EnumDesEchoPatternValue)));
- diagnosisItems.Add(GetEnumItem(typeof(EnumDesLesionBoundaryValue)));
- diagnosisItems.Add(GetEnumItem(typeof(EnumDesMarginValue)));
- diagnosisItems.Add(GetEnumItem(typeof(EnumCalcificationsValue), "Calcification"));
- diagnosisItems.Add(GetEnumItem(typeof(EnumDesLiverShapeValue)));
- diagnosisItems.Add(GetEnumItem(typeof(EnumDesLiverBoundaryValue)));
- diagnosisItems.Add(GetEnumItem(typeof(EnumDesLiverEchoTextureValue)));
- diagnosisItems.Add(GetEnumItem(typeof(EnumDesThyroidEchoPatternValue)));
- diagnosisItems.Add(GetEnumItem(typeof(EnumDesThyroidShapeValue)));
- diagnosisItems.Add(GetEnumItem(typeof(EnumDesThyroidMarginValue)));
- diagnosisItems.Add(GetEnumItem(typeof(EnumDesThyroidEchogenicFociValue)));
- //局灶和弥漫区分
- diagnosisItems.Add(GetEnumItem(typeof(DiagnosisBreastLabelEnum), "BreastLocalLesion", includeFields: new List<string> { "Lipomyoma", "BIRads2", "BIRads3" }));
- diagnosisItems.Add(GetEnumItem(typeof(DiagnosisBreastLabelEnum), "BreastDiffuseLesion", includeFields: new List<string> { "BIRads4A", "BIRads4B", "BIRads4C", "BIRads5" }));
- diagnosisItems.Add(GetEnumItem(typeof(DiagnosisLiverLabelEnum), "LiverLocalLesion", includeFields: new List<string> { "Hyperechoic", "HHE", "CYST", "PossibleCancer" }));
- diagnosisItems.Add(GetEnumItem(typeof(DiagnosisLiverLabelEnum), "LiverDiffuseLesion", includeFields: new List<string> { "FattyLiver", "DiffuseLesions", "Cirrhosis", "PCLD" }));
- diagnosisItems.Add(GetEnumItem(typeof(AIThyroidLabelEnum), "ThyroidLocalLesion", includeFields: new List<string> { "TIRADS2", "TIRADS3", "TIRADS4a", "TIRADS4b", "TIRADS4c", "TIRADS5" }));
- diagnosisItems.Add(GetEnumItem(typeof(AIThyroidLabelEnum), "ThyroidDiffuseLesion", includeFields: new List<string> { "DiffuseDisease" }));
- var resultData = new GetDiagnosisEnumItemsResult { Source = diagnosisItems };
- return await Task.FromResult(resultData);
- }
- private EnumItemDTO GetEnumItem(Type enumType, string keyCode = "", List<string> excludeFields = null, List<string> includeFields = null)
- {
- keyCode = !string.IsNullOrWhiteSpace(keyCode) ? keyCode : enumType.Name.ToString().Replace("EnumDes", "").Replace("Enum", "").Replace("Value", "");
- var enumNames = Enum.GetNames(enumType).ToList();
- if (excludeFields != null && excludeFields.Any())
- {
- enumNames = enumNames.Except(excludeFields).ToList();
- }
- if (includeFields != null && includeFields.Any())
- {
- enumNames = enumNames.Intersect(includeFields).ToList();
- }
- var children = new List<EnumFieldDTO>();
- foreach (var val in enumNames)
- {
- var id = (int)enumType.GetField(val).GetValue(val);
- var fieldValue = val.ToString();
- if (enumType == typeof(DiagnosisLiverLabelEnum) && fieldValue == "Hyperechoic")
- {
- fieldValue = "LiverHyperechoic";
- }
- children.Add(new EnumFieldDTO
- {
- Id = id,
- Value = fieldValue,
- });
- }
- return new EnumItemDTO
- {
- Code = keyCode,
- Children = children,
- };
- }
- /// <summary>
- /// 查询病灶轮廓的关键点
- /// </summary>
- /// <param name="request">查询病灶轮廓的关键点请求实体</param>
- /// <returns>关键点集合</returns>
- /// <value></value>
- /// <errorCodes></errorCodes>
- public async Task<List<DiagnosisKeyPointDTO>> GetKeyPointsOfContourAsync(GetKeyPointsOfContourRequest request)
- {
- var contourPoints = request.Contours.Select(c => new Point2D
- {
- X = c.X,
- Y = c.Y
- }).ToArray();
- var ls = request.LesionSize;
- var horizontalP1 = new Point2D(ls.HorizontalPoint1.X, ls.HorizontalPoint1.Y);
- var horizontalP2 = new Point2D(ls.HorizontalPoint2.X, ls.HorizontalPoint2.Y);
- var verticalP1 = new Point2D(ls.VerticalPoint1.X, ls.VerticalPoint1.Y);
- var verticalP2 = new Point2D(ls.VerticalPoint2.X, ls.VerticalPoint2.Y);
- var lesionSize = new LesionSize(horizontalP1, horizontalP2, verticalP1, verticalP2);
- // lesionSize.HorizontalLengthInPixel = ls.HorizontalLengthInPixel;
- // lesionSize.VerticalLengthInPixel = ls.VerticalLengthInPixel;
- var aiResult = ContourModifyHelper.KeyPointsOfContour(contourPoints, lesionSize);
- var resultData = KeyPointToDto(aiResult);
- return await Task.FromResult(resultData);
- }
- /// <summary>
- /// 移动光标,查询受影响关键点
- /// </summary>
- /// <param name="request">移动光标,查询受影响关键点请求实体</param>
- /// <returns>受影响关键点下标</returns>
- /// <value></value>
- /// <errorCodes></errorCodes>
- public async Task<List<int>> AffectedKeyPointsByDragActionAsync(AffectedKeyPointsByDragActionRequest request)
- {
- var origKeyPoints = request.KeyPoints.Select(c => new KeyPointInfo
- {
- Type = (EnumKeyPointType)c.Type,
- IndexInContour = c.IndexInContour,
- Point = new Point2D(c.Point.X, c.Point.Y)
- }).ToArray();
- var mousePoint = new Point2D(request.MousePoint.X, request.MousePoint.Y);
- var resultData = ContourModifyHelper.AffectedKeyPointsByDragAction(origKeyPoints, mousePoint).ToList();
- return await Task.FromResult(resultData);
- }
- /// <summary>
- /// 拖动光标,查询所有轮廓点和关键点
- /// </summary>
- /// <param name="request">拖动光标,查询所有轮廓点和关键点请求实体</param>
- /// <returns>所有轮廓点和关键点</returns>
- /// <value></value>
- /// <errorCodes></errorCodes>
- public async Task<ContourAndKeyPointsAfterDragResult> ContourAndKeyPointsAfterDragAsync(ContourAndKeyPointsAfterDragRequest request)
- {
- var origContourPoints = request.Contours.Select(c => new Point2D
- {
- X = c.X,
- Y = c.Y
- }).ToArray();
- var origKeyPoints = request.KeyPoints.Select(c => new KeyPointInfo
- {
- Type = (EnumKeyPointType)c.Type,
- IndexInContour = c.IndexInContour,
- Point = new Point2D(c.Point.X, c.Point.Y)
- }).ToArray();
- var dragStartPoint = new Point2D(request.StartPoint.X, request.StartPoint.Y);
- var dragEndPoint = new Point2D(request.EndPoint.X, request.EndPoint.Y);
- ContourModifyHelper.ContourAndKeyPointsAfterDrag(origContourPoints, origKeyPoints, dragStartPoint, dragEndPoint
- , out Point2D[] dstContourPoints, out KeyPointInfo[] dstKeyPoints, out int[] affectedKeyPointIndexes);
- var dstContours = PointToDto(dstContourPoints);
- var dstKeys = KeyPointToDto(dstKeyPoints);
- var resultData = new ContourAndKeyPointsAfterDragResult
- {
- DstContours = dstContours,
- DstKeyPoints = dstKeys,
- AffectedKeyPointIndexes = affectedKeyPointIndexes.ToList(),
- };
- return await Task.FromResult(resultData);
- }
- /// <summary>
- /// 画轮廓模式,查询鼠标位置到轮廓线的最短距离
- /// </summary>
- /// <param name="request">画轮廓模式,查询鼠标位置到轮廓线的最短距离请求实体</param>
- /// <returns>鼠标离轮廓线的距离,高亮点的下标</returns>
- /// <value></value>
- /// <errorCodes></errorCodes>
- public async Task<MinimumDistanceToContourPointsResult> MinimumDistanceToContourPointsAsync(MinimumDistanceToContourPointsRequest request)
- {
- var origContourPoints = request.ContourPoints.Select(c => new Point2D
- {
- X = c.X,
- Y = c.Y
- }).ToArray();
- var mousePoint = new Point2D(request.MousePoint.X, request.MousePoint.Y);
- var distance = ContourModifyHelper.MinimumDistanceToContourPoints(origContourPoints, mousePoint, out int closestPointIndex);
- var resultData = new MinimumDistanceToContourPointsResult
- {
- DistanceCaught = distance,
- ClosestPointIndex = closestPointIndex,
- };
- return await Task.FromResult(resultData);
- }
- /// <summary>
- /// 画轮廓模式,合并新旧轮廓
- /// </summary>
- /// <param name="request">画轮廓模式,查询鼠标位置到轮廓线的最短距离请求实体</param>
- /// <returns>合并后的完整轮廓线,合并后的横纵径尺寸结果</returns>
- /// <value></value>
- /// <errorCodes></errorCodes>
- public async Task<ContourMergeResult> ContourMergeAsync(ContourMergeRequest request)
- {
- var origContourPoints = request.ContourPoints.Select(c => new Point2D
- {
- X = c.X,
- Y = c.Y
- }).ToArray();
- var ls = request.LesionSize;
- var horizontalP1 = new Point2D(ls.HorizontalPoint1.X, ls.HorizontalPoint1.Y);
- var horizontalP2 = new Point2D(ls.HorizontalPoint2.X, ls.HorizontalPoint2.Y);
- var verticalP1 = new Point2D(ls.VerticalPoint1.X, ls.VerticalPoint1.Y);
- var verticalP2 = new Point2D(ls.VerticalPoint2.X, ls.VerticalPoint2.Y);
- var lesionSize = new LesionSize(horizontalP1, horizontalP2, verticalP1, verticalP2);
- // lesionSize.HorizontalLengthInPixel = ls.HorizontalLengthInPixel;
- // lesionSize.VerticalLengthInPixel = ls.VerticalLengthInPixel;
- var drawingNewContourPoints = request.DrawingNewContourPoints.Select(c => new Point2D
- {
- X = c.X,
- Y = c.Y
- }).ToArray();
- var aiResult = ContourModifyHelper.ContourMerge(origContourPoints, lesionSize, drawingNewContourPoints, out Point2D[] dstContourPoints, out LesionSize dstLesionSize);
- var dstContours = PointToDto(dstContourPoints);
- var resultData = new ContourMergeResult
- {
- DstContours = dstContours,
- DstLesionSize = new WingInterfaceLibrary.DTO.Comment.AIDiagnosisLesionSize
- {
- HorizontalPoint1 = new WingInterfaceLibrary.DTO.Comment.AIDiagnosisPoint2D { X = dstLesionSize.HorizontalPoint1.X, Y = dstLesionSize.HorizontalPoint1.Y },
- HorizontalPoint2 = new WingInterfaceLibrary.DTO.Comment.AIDiagnosisPoint2D { X = dstLesionSize.HorizontalPoint2.X, Y = dstLesionSize.HorizontalPoint2.Y },
- VerticalPoint1 = new WingInterfaceLibrary.DTO.Comment.AIDiagnosisPoint2D { X = dstLesionSize.VerticalPoint1.X, Y = dstLesionSize.VerticalPoint1.Y },
- VerticalPoint2 = new WingInterfaceLibrary.DTO.Comment.AIDiagnosisPoint2D { X = dstLesionSize.VerticalPoint2.X, Y = dstLesionSize.VerticalPoint2.Y },
- HorizontalLengthInPixel = dstLesionSize.HorizontalLengthInPixel,
- VerticalLengthInPixel = dstLesionSize.VerticalLengthInPixel,
- },
- };
- return await Task.FromResult(resultData);
- }
- /// <summary>
- /// 获取颈动脉ai报告数据
- /// </summary>
- /// <param name="request">生成AI报告请求实体</param>
- /// <returns></returns>
- private async Task<DiagnosisReportResult> GetCarotidAIMeasureResult(DiagnosisReportRequest request)
- {
- var result = new DiagnosisReportResult()
- {
- DiagnosisConclusion = DiagnosisConclusionEnum.NoObviousLesion
- };
- var reportItems = new List<DataItemDTO>();
- 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<CarotidAIMeasureResult>(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);
- var carotidResultInfos = GetCarotidResultInfos(leftData);
- if (carotidResultInfos.Any(x => x.DetectedObjects.Any(x => x.Label == 1)))
- {
- //有斑块
- reportItems.Add(new DataItemDTO { Key = "bd170b6a-e052-42f0-a778-4ec85138c1c6;33c0aaf8-e48e-4474-af68-b47d2378073f;LeftConclusion", Value = FormatterPlaceholder2($"OnePlaque") });
- var info = GetReportDetectedObject(carotidResultInfos, 0.1);
- var reportDetectedObject = info.Item1;
- var maxArea = Math.Round(info.Item2 * 0.1, 2);
- reportItems.Add(new DataItemDTO { Key = "d2449fa2-70e7-45d1-80e3-f69c62652186;98d1e829-b0ee-440d-ae3b-02ff74521357;LeftPlaqueThick", Value = maxArea.ToString() });
- var locationItem = GetDescription(reportDetectedObject, DiagnosisDescriptionEnum.QlaqueLocation);
- if (locationItem != null)
- {
- reportItems.Add(new DataItemDTO { Key = "6f57bb90-6492-421e-ad3e-6c684b7f7452;6e36fa47-edb2-4ed8-8521-ddb9e1fa5536;LeftPlaquePosition", Value = FormatterPlaceholder2($"{locationItem.Value}") });
- }
- var echoItem = GetDescription(reportDetectedObject, DiagnosisDescriptionEnum.QlaqueEchoPattern);
- if (echoItem != null)
- {
- reportItems.Add(new DataItemDTO { Key = "ccef71cd-1c52-4614-a54f-d6d58cb8c586;d440eb6e-2630-4787-8700-486d097ba9f1;LeftPlaqueEcho", Value = FormatterPlaceholder2($"{echoItem.Value}") });
- }
- var rateOfStenosis = GetDescription(reportDetectedObject, DiagnosisDescriptionEnum.CarotidRateOfStenosis);
- if (rateOfStenosis != null)
- {
- var rateOfStenosisValue = string.Empty;
- var rate = rateOfStenosis.Value.ToFloat() * 100;
- if (rate < 30)
- {
- rateOfStenosisValue = "Normal";
- }
- else if (rate >= 30 && rate < 50)
- {
- rateOfStenosisValue = "Mild";
- }
- else if (rate >= 50 && rate < 70)
- {
- rateOfStenosisValue = "Moderate";
- }
- else if (rate >= 70 && rate < 100)
- {
- rateOfStenosisValue = "Severe";
- }
- else
- {
- rateOfStenosisValue = "Blockage";
- }
- reportItems.Add(new DataItemDTO { Key = "e3610e58-79c4-4e18-94c9-8928583b9dab;e6da9399-b849-4017-a3b8-e3212f55c4a4;LeftStenosisRate", Value = FormatterPlaceholder2(rateOfStenosisValue) });
- }
- var innerDiameter = GetDescription(reportDetectedObject, DiagnosisDescriptionEnum.CarotidInnerDiameter);
- if (innerDiameter != null && !string.IsNullOrWhiteSpace(innerDiameter.Value))
- {
- var diagnosisMeasuringLine = JsonConvert.DeserializeObject<AIDiagnosisMeasuringLine>(innerDiameter.Value);
- var measuringLineLengthInPixel = Math.Round(diagnosisMeasuringLine.MeasuringLineLengthInPixel * 0.1, 2);
- reportItems.Add(new DataItemDTO { Key = "9a6f96bb-b81e-407d-bc84-9d9815e96696;fe948295-b065-46b9-ab25-fe80144d7bff;LeftCarotidAD", Value = measuringLineLengthInPixel.ToString() });
- }
- }
- else
- {
- reportItems.Add(new DataItemDTO { Key = "bd170b6a-e052-42f0-a778-4ec85138c1c6;33c0aaf8-e48e-4474-af68-b47d2378073f;LeftConclusion", Value = FormatterPlaceholder2($"NoPlaque2") });
- }
- }
- else
- {
- reportItems.Add(new DataItemDTO { Key = "bd170b6a-e052-42f0-a778-4ec85138c1c6;33c0aaf8-e48e-4474-af68-b47d2378073f;LeftConclusion", Value = FormatterPlaceholder2($"NoPlaque2") });
- }
- //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<CarotidAIMeasureResult>(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);
- var carotidResultInfos = GetCarotidResultInfos(rightData);
- if (carotidResultInfos.Any(x => x.DetectedObjects.Any(x => x.Label == 1)))
- {
- //有斑块
- reportItems.Add(new DataItemDTO { Key = "ec4c775e-601c-48cc-a1a9-f39c8629e3f7;9918912e-b702-4a2b-8b4f-61dcfb846be3;RightConclusion", Value = FormatterPlaceholder2($"OnePlaque") });
- var info = GetReportDetectedObject(carotidResultInfos, 0.1);
- var reportDetectedObject = info.Item1;
- var maxArea = Math.Round(info.Item2 * 0.1, 2);
- reportItems.Add(new DataItemDTO { Key = "8e467ffb-da00-4d34-9aac-34e4e8f91844;46166cb6-ad3a-4ca2-821e-bd872137fa64;RightPlaqueThick", Value = maxArea.ToString() });
- var locationItem = GetDescription(reportDetectedObject, DiagnosisDescriptionEnum.QlaqueLocation);
- if (locationItem != null)
- {
- reportItems.Add(new DataItemDTO { Key = "1153870e-10c8-4674-99bf-108937db1060;053091d2-8ea0-4fcb-a222-00b46f60d12f;RightPlaquePosition", Value = FormatterPlaceholder2($"{locationItem.Value}") });
- }
- var echoItem = GetDescription(reportDetectedObject, DiagnosisDescriptionEnum.QlaqueEchoPattern);
- if (echoItem != null)
- {
- reportItems.Add(new DataItemDTO { Key = "c82e8655-169f-42be-ac99-5e7a56329924;e77f550d-37f3-492a-98dd-a981535383a5;RightPlaqueEcho", Value = FormatterPlaceholder2($"{echoItem.Value}") });
- }
- var rateOfStenosis = GetDescription(reportDetectedObject, DiagnosisDescriptionEnum.CarotidRateOfStenosis);
- if (rateOfStenosis != null)
- {
- var rateOfStenosisValue = string.Empty;
- var rate = rateOfStenosis.Value.ToFloat() * 100;
- if (rate < 30)
- {
- rateOfStenosisValue = "Normal";
- }
- else if (rate >= 30 && rate < 50)
- {
- rateOfStenosisValue = "Mild";
- }
- else if (rate >= 50 && rate < 70)
- {
- rateOfStenosisValue = "Moderate";
- }
- else if (rate >= 70 && rate < 100)
- {
- rateOfStenosisValue = "Severe";
- }
- else
- {
- rateOfStenosisValue = "Blockage";
- }
- reportItems.Add(new DataItemDTO { Key = "b0092e8a-25ba-4690-b70f-e3525e6aaa39;2e742ddc-fa90-47bb-ac24-664238773b30;RightStenosisRate", Value = FormatterPlaceholder2(rateOfStenosisValue) });
- }
- var innerDiameter = GetDescription(reportDetectedObject, DiagnosisDescriptionEnum.CarotidInnerDiameter);
- if (innerDiameter != null && !string.IsNullOrWhiteSpace(innerDiameter.Value))
- {
- var diagnosisMeasuringLine = JsonConvert.DeserializeObject<AIDiagnosisMeasuringLine>(innerDiameter.Value);
- var measuringLineLengthInPixel = Math.Round(diagnosisMeasuringLine.MeasuringLineLengthInPixel * 0.1, 2);
- reportItems.Add(new DataItemDTO { Key = "8c7543e9-95f2-4862-b2aa-4c4cb032948e;9f8e95ee-a262-41c2-9d4b-efbc7974b397;RightCarotidAD", Value = measuringLineLengthInPixel.ToString() });
- }
- }
- else
- {
- reportItems.Add(new DataItemDTO { Key = "ec4c775e-601c-48cc-a1a9-f39c8629e3f7;9918912e-b702-4a2b-8b4f-61dcfb846be3;RightConclusion", Value = FormatterPlaceholder2($"NoPlaque2") });
- }
- }
- else
- {
- reportItems.Add(new DataItemDTO { Key = "ec4c775e-601c-48cc-a1a9-f39c8629e3f7;9918912e-b702-4a2b-8b4f-61dcfb846be3;RightConclusion", Value = FormatterPlaceholder2($"NoPlaque2") });
- }
- Logger.WriteLineInfo($"AIDiagnosisService package carotidAIMeasureResult finished, CarotidLeftRemedicalCode:{leftData?.RemedicalCode}, CarotidLeft:{leftData?.CarotidResult?.MeasureResult}, CarotidRightRemedicalCode:{rightData?.RemedicalCode}, CarotidRight:" + rightData?.CarotidResult?.MeasureResult);
- }
- result.CarotidItems = reportItems;
- return result;
- }
- private string FormatterPlaceholder2(string val)
- {
- return string.Format("#@{0}@#", val);
- }
- private string FormatterPlaceholderArray(string format, string[] pars)
- {
- var parameters = string.Join(',', pars);
- parameters = parameters.Replace("#@", "&@").Replace("@#", "@&");
- return FormatterPlaceholder(format + $"[{parameters}]");
- }
- private string FormatterPlaceholder(string languageKey)
- {
- languageKey = languageKey?.Trim() ?? string.Empty;
- if (!string.IsNullOrWhiteSpace(languageKey))
- {
- return string.Format("#@{0}@#", languageKey);
- }
- return string.Empty;
- }
- private List<WingInterfaceLibrary.DTO.Comment.AIDiagnosisResultPerOrgan> GetCarotidResultInfos(DiagnosisRemicalDTO remedical)
- {
- var diagnosisResult = remedical.DiagnosisResult;
- var carotidResultInfos = new List<WingInterfaceLibrary.DTO.Comment.AIDiagnosisResultPerOrgan>();
- if (diagnosisResult != null && diagnosisResult.Any())
- {
- foreach (var item in diagnosisResult)
- {
- var carotids = item.DiagResultsForEachOrgan?.Where(x => x.Organ == DiagnosisOrganEnum.CarotidArtery);
- if (carotids != null && carotids.Any())
- {
- carotidResultInfos.AddRange(carotids);
- }
- }
- }
- return carotidResultInfos;
- }
- private Tuple<Manage.AIDetectedObject, int, string, double> GetReportDetectedObject(List<Manage.AIDiagnosisResultPerOrgan> carotidResultInfos, double physicalPerPixel)
- {
- Manage.AIDetectedObject detectedObject = null;
- var maxArea = 0;
- var maxAreaString = string.Empty;
- double verticalLengthInPixel = 0;
- double horizontalLengthInPixel = 0;
- foreach (var organInfo in carotidResultInfos)
- {
- var plaqueDetectedObjects = organInfo.DetectedObjects.Where(x => x.Label == 1);
- if (plaqueDetectedObjects == null || !plaqueDetectedObjects.Any())
- {
- continue;
- }
- foreach (var dob in plaqueDetectedObjects)
- {
- var lesionSizeDes = dob.Descriptions?.FirstOrDefault(x => x.Type == DiagnosisDescription.LesionSize);
- if (lesionSizeDes != null && !string.IsNullOrWhiteSpace(lesionSizeDes.Value))
- {
- var diagnosisLesionSize = JsonConvert.DeserializeObject<Manage.AIDiagnosisLesionSize>(lesionSizeDes.Value);
- var currArea = diagnosisLesionSize.VerticalLengthInPixel * diagnosisLesionSize.HorizontalLengthInPixel;
- if (detectedObject == null || currArea > maxArea)
- {
- detectedObject = dob;
- maxArea = currArea;
- verticalLengthInPixel = Math.Round(diagnosisLesionSize.VerticalLengthInPixel * physicalPerPixel, 2);
- horizontalLengthInPixel = Math.Round(diagnosisLesionSize.HorizontalLengthInPixel * physicalPerPixel, 2);
- maxAreaString = $"{horizontalLengthInPixel} × {verticalLengthInPixel}";
- }
- }
- }
- }
- return new Tuple<Manage.AIDetectedObject, int, string, double>(detectedObject, maxArea, maxAreaString, Math.Min(verticalLengthInPixel, horizontalLengthInPixel));
- }
- private Tuple<WingInterfaceLibrary.DTO.Comment.AIDetectedObject, int, string, double> GetReportDetectedObject(List<WingInterfaceLibrary.DTO.Comment.AIDiagnosisResultPerOrgan> carotidResultInfos, double physicalPerPixel)
- {
- WingInterfaceLibrary.DTO.Comment.AIDetectedObject detectedObject = null;
- var maxArea = 0;
- var maxAreaString = string.Empty;
- double verticalLengthInPixel = 0;
- double horizontalLengthInPixel = 0;
- foreach (var organInfo in carotidResultInfos)
- {
- var plaqueDetectedObjects = organInfo.DetectedObjects.Where(x => x.Label == 1);
- if (plaqueDetectedObjects == null || !plaqueDetectedObjects.Any())
- {
- continue;
- }
- foreach (var dob in plaqueDetectedObjects)
- {
- var lesionSizeDes = dob.Descriptions?.FirstOrDefault(x => x.Type == DiagnosisDescriptionEnum.LesionSize);
- if (lesionSizeDes != null && !string.IsNullOrWhiteSpace(lesionSizeDes.Value))
- {
- var diagnosisLesionSize = JsonConvert.DeserializeObject<Manage.AIDiagnosisLesionSize>(lesionSizeDes.Value);
- var currArea = diagnosisLesionSize.VerticalLengthInPixel * diagnosisLesionSize.HorizontalLengthInPixel;
- if (detectedObject == null || currArea > maxArea)
- {
- detectedObject = dob;
- maxArea = currArea;
- verticalLengthInPixel = Math.Round(diagnosisLesionSize.VerticalLengthInPixel * physicalPerPixel, 2);
- horizontalLengthInPixel = Math.Round(diagnosisLesionSize.HorizontalLengthInPixel * physicalPerPixel, 2);
- maxAreaString = $"{horizontalLengthInPixel} × {verticalLengthInPixel}";
- }
- }
- }
- }
- return new Tuple<WingInterfaceLibrary.DTO.Comment.AIDetectedObject, int, string, double>(detectedObject, maxArea, maxAreaString, Math.Min(verticalLengthInPixel, horizontalLengthInPixel));
- }
- private WingInterfaceLibrary.DTO.Comment.AIDiagnosisDescription GetDescription(WingInterfaceLibrary.DTO.Comment.AIDetectedObject detectedObject, DiagnosisDescriptionEnum descriptionType)
- {
- var description = detectedObject?.Descriptions.FirstOrDefault(x => x.Type == descriptionType);
- return description;
- }
- private async Task<BaseDiagnosis> CreateDiagnosisManagerAsync(DiagnosisReportRequest request)
- {
- var recordResults = new List<DiagnosisPerImageModel>();
- 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<List<WingAIDiagnosisService.Manage.AIDiagnosisResultPerOrgan>>(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);
- case DiagnosisOrganEnum.Thyroid://甲状腺
- return new ThyroidDiagnosis(recordResults, request.Organ);
- case DiagnosisOrganEnum.CarotidArtery://颈动脉
- return new CarotidDiagnosis(recordResults, request.Organ);
- default:
- throw new Exception($"not support organ type:{request.Organ.ToString()}");
- }
- }
- private async Task<CarotidResultDTO> 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 (imageData.ImageCount <= DiagnosisHelper.CarotidMinImageCounts)
- {
- return new CarotidResultDTO
- {
- CarotidScanType = (CarotidScanTypeEnum)resampleInputData.ScanType,
- CarotidScanDirection = (CarotidScanDirectionEnum)resampleInputData.CarotidScanDirection,
- };
- }
- return new CarotidResultDTO
- {
- CarotidScanType = (CarotidScanTypeEnum)resampleInputData.ScanType,
- CarotidScanDirection = (CarotidScanDirectionEnum)resampleInputData.CarotidScanDirection,
- };
- if (resampleResult.ResampleErrorCode == ResampleErrorCode.Success)
- {
- var carotidAIImageTokens = new List<CarotidAIImage>();
- 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<string>();
- 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.MdlZipFilePath) && File.Exists(resampleInputData.MdlZipFilePath))
- {
- var mdlFileTuple = await UploadFileTupleAsync(resampleInputData.MdlZipFilePath, Path.GetFileName(resampleInputData.MdlZipFilePath));
- mdlFileFileSize = mdlFileTuple.Item2;
- File.Delete(resampleInputData.MdlZipFilePath);
- resampleInputData.MdlZipFilePath = 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.MdlZipFilePath,
- 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<Bgr, byte>();
- //识别左右颈信息
- scanType = _recognizeCarotidType.RecognizeType(image);
- }
- }
- resampleInputData.ScanDistance = scanDistance;
- resampleInputData.ScanType = scanType;
- resampleInputData.CarotidScanDirection = direction;
- resampleResult = ResampleModel.Instance.Resample(vinnoImageData, resampleInputData, _workerLevel);
- return resampleResult;
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="filePath"></param>
- private async Task<List<string>> SurfaceFile(string filePath)
- {
- var fileUrls = new List<string>();
- try
- {
- 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<Gray, byte>();
- CvInvoke.Imencode(".jpg", image, buf, new KeyValuePair<ImwriteFlags, int>(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);
- }
- }
- }
- }
- catch (Exception ex)
- {
- Logger.WriteLineWarn($"SurfaceFile err, ex:{ex}");
- }
- 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 SKBitmap CreateBitmap(byte[] imageData)
- {
- try
- {
- return SKBitmap.Decode(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<T>(List<T> results) where T : AIDiagnosisPerImageModel
- {
- var diagnosisConclusions = new List<DiagnosisConclusion>();
- foreach (var imageResult in results)
- {
- foreach (var diagnosisResult in imageResult.DiagResultsForEachOrgan)
- {
- var benignLabels = new List<int>();
- var malignantLabels = new List<int>();
- if (diagnosisResult.Organ == DiagnosisOrganEnum.Breast)
- {
- benignLabels = new List<int> { 1, 2, 3 };
- malignantLabels = new List<int> { 4, 5, 6, 7 };
- }
- else if (diagnosisResult.Organ == DiagnosisOrganEnum.Liver)
- {
- benignLabels = new List<int> { 1, 2, 3, 5, 6, 7, 8 };
- malignantLabels = new List<int> { 4 };
- }
- else if (diagnosisResult.Organ == DiagnosisOrganEnum.Thyroid)
- {
- benignLabels = new List<int> { 1, 2, 7 };
- malignantLabels = new List<int> { 3, 4, 5, 6 };
- }
- else if (diagnosisResult.Organ == DiagnosisOrganEnum.CarotidArtery)
- {
- benignLabels = new List<int> { 1 };
- malignantLabels = new List<int> { };
- }
- 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<DiagnosisOrganEnum> GetDiagnosisOrgans(List<AIDiagnosisPerImageModel> results)
- {
- var diagnosisOrgans = new List<DiagnosisOrganEnum>();
- 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)
- {
- if (diagnosisResult.Organ == DiagnosisOrganEnum.CarotidArtery || diagnosisResult.DetectedObjects?.Any() == true)
- {
- diagnosisOrgans.Add((DiagnosisOrganEnum)diagnosisResult.Organ);
- }
- }
- }
- }
- return diagnosisOrgans.Distinct().ToList();
- }
- private List<DiagnosisOrganEnum> GetDiagnosisOrgans(List<DiagnosisPerImageModel> results)
- {
- var diagnosisOrgans = new List<DiagnosisOrganEnum>();
- 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<int, AIDiagResultPerImg> NormalDiagnosis(string relationCode, string fileUrl, VinnoImageData imageData)
- {
- var results = new Dictionary<int, AIDiagResultPerImg>();
- try
- {
- var imageCount = imageData.ImageCount;
- Logger.WriteLineInfo($"AIDiagnosisService diagnosis start, relationCode:{relationCode}, fileUrl:{fileUrl}, imageCount:{imageCount}");
- if (imageCount > 0)
- {
- var diagId = _diagSystem.StartEvalutationOfMultipleImageBatches(imageCount);
- for (var i = 0; i < imageCount; i++)
- {
- var image = imageData.GetImage(i);
- using (var bitmap = CreateBitmap(image))
- {
- using (var rawImage = new RawImage(bitmap.Bytes, bitmap.Width, bitmap.Height, MapTo(bitmap.ColorType)))
- {
- _diagSystem.PushOneBatchOfImagesAsync(diagId, new List<RawImage> { rawImage });
- }
- }
- }
- results = _diagSystem.GetEvaluationsOfPushedMultipleImageBatches(diagId);
- Logger.WriteLineInfo($"AIDiagnosisService diagnosis successfully");
- }
- }
- catch (Exception ex)
- {
- Logger.WriteLineWarn($"AIDiagnosisService NormalDiagnosis err, {ex}");
- }
- return results;
- }
- /// <summary>
- /// 保存AI诊断结果
- /// </summary>
- /// <param name="relationCode"></param>
- /// <param name="fileUrl"></param>
- /// <param name="diagnosisResultInfos"></param>
- /// <returns></returns>
- private async Task<bool> AddDiagnosisResultInfosAsync(string relationCode, string fileUrl, List<AIDiagnosisPerImageModel> diagnosisResultInfos
- , DateTime? createTime = null, DateTime? updateTime = null, bool syncOthers = true)
- {
- try
- {
- var resultInfos = new List<DiagnosisResultDTO>();
- for (var i = 0; i < diagnosisResultInfos.Count; i++)
- {
- resultInfos.Add(new DiagnosisResultDTO
- {
- Index = i,
- DiagnosisResult = Newtonsoft.Json.JsonConvert.SerializeObject(diagnosisResultInfos[i]),
- });
- }
- var addRequest = new AddDiagnosisResultInfosDBRequest
- {
- RelationCode = relationCode,
- FileUrl = fileUrl,
- DiagnosisResultInfos = resultInfos,
- CreateTime = createTime,
- UpdateTime = updateTime,
- SyncOthers = syncOthers,
- };
- if (syncOthers)
- {
- _diagnosisResultDBService.AddDiagnosisResultInfosAsync(addRequest);
- }
- else
- {
- await _diagnosisResultDBService.AddDiagnosisResultInfosAsync(addRequest);
- }
- return true;
- }
- catch (Exception ex)
- {
- Logger.WriteLineWarn($"AIDiagnosisService AddDiagnosisResultInfosAsync err, ex:{ex}");
- return false;
- }
- }
- /// <summary>下载文件</summary>
- /// <param name="fileUrl"></param>
- /// <returns></returns>
- private async Task<string> 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;
- }
- /// <summary>
- /// 上传文件
- /// </summary>
- /// <param name="filePath"></param>
- /// <param name="fileName"></param>
- /// <returns></returns>
- private async Task<string> 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<Tuple<string, long>> UploadFileWithSizeAsync(string filePath, string fileName)
- {
- var fileToken = "";
- long size = 0;
- using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
- {
- size = fileStream.Length;
- byte[] buffer = new byte[fileStream.Length];
- fileStream.Read(buffer, 0, buffer.Length);
- fileToken = await DoUploadFile(fileName, buffer);
- }
- return new Tuple<string, long>(fileToken, size);
- }
- /// <summary>
- /// 上传文件
- /// </summary>
- /// <param name="filePath"></param>
- /// <param name="fileName"></param>
- /// <returns></returns>
- private async Task<Tuple<string, long>> 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<string, long>(fileToken, size);
- }
- /// <summary>
- /// 上传文件
- /// </summary>
- /// <param name="fileName"></param>
- /// <param name="fileData"></param>
- /// <returns></returns>
- async Task<string> DoUploadFile(string fileName, byte[] fileData)
- {
- var requestHeads = new Dictionary<string, string>();
- 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;
- }
- }
- /// <summary>
- /// 执行请求
- /// </summary>
- /// <param name="httpRequestMessage"></param>
- /// <typeparam name="T"></typeparam>
- /// <returns></returns>
- public async Task<bool> 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;
- }
- }
- private List<WingInterfaceLibrary.DTO.Comment.AIDiagnosisPoint2D> PointToDto(Point2D[] points)
- {
- var dstContours = new List<WingInterfaceLibrary.DTO.Comment.AIDiagnosisPoint2D>();
- foreach (var p in points)
- {
- dstContours.Add(new WingInterfaceLibrary.DTO.Comment.AIDiagnosisPoint2D
- {
- X = p.X,
- Y = p.Y
- });
- }
- return dstContours;
- }
- private List<DiagnosisKeyPointDTO> KeyPointToDto(KeyPointInfo[] points)
- {
- var dstKeys = new List<DiagnosisKeyPointDTO>();
- foreach (var point in points)
- {
- dstKeys.Add(new DiagnosisKeyPointDTO
- {
- Type = (DiagnosisKeyPointType)point.Type,
- IndexInContour = point.IndexInContour,
- Point = new WingInterfaceLibrary.DTO.Comment.AIDiagnosisPoint2D
- {
- X = point.Point.X,
- Y = point.Point.Y,
- },
- });
- }
- return dstKeys;
- }
- /// <summary>
- /// 创建缩略图文件
- /// </summary>
- /// <param name="vinnoImage"></param>
- /// <param name="requestHeight"></param>
- /// <param name="quality"></param>
- /// <param name="fullPath"></param>
- private void CreateThumbnailFile(string filePath, int requestHeight, int quality, string fullPath)
- {
- using (var fileStream = new FileStream(filePath, FileMode.Open))
- {
- var size = fileStream.Length;
- byte[] buffer = new byte[fileStream.Length];
- fileStream.Read(buffer, 0, buffer.Length);
- byte[] compressedData = buffer;
- using (var ms = new MemoryStream(compressedData))
- {
- using (var image = SKBitmap.Decode(ms))
- {
- var ratio = (double)requestHeight / image.Height;
- if (ratio < 1)
- {
- var width = (int)(image.Width * ratio);
- var height = (int)(image.Height * ratio);
- SKBitmap tempImage = image;
- if (image.Width != width || image.Height != height)
- {
- tempImage = image.Resize(new SKImageInfo(width, height), SKFilterQuality.High);
- }
- try
- {
- using (var map = new SKPixmap(new SKImageInfo(tempImage.Width, tempImage.Height, tempImage.ColorType), tempImage.GetPixels()))
- {
- using (var stream = new SKDynamicMemoryWStream())
- {
- SKPixmap.Encode(stream, map, SKEncodedImageFormat.Jpeg, quality);
- compressedData = stream.CopyToData().ToArray();
- }
- }
- }
- catch (Exception ex)
- {
- throw ex;
- }
- finally
- {
- tempImage.Dispose();
- }
- }
- }
- }
- using (var fs = File.Create(fullPath))
- {
- fs.Write(compressedData, 0, compressedData.Length);
- }
- }
- }
- /// <summary>
- /// 是否与当前存储匹配
- /// </summary>
- /// <param name="value"></param>
- /// <returns></returns>
- private bool MatchCurrentStorage(string value)
- {
- if (!string.IsNullOrWhiteSpace(value))
- {
- var cfsServerUrl = EnvironmentConfigs.Storage.CFSServerUrl.Replace("http://", "").Replace("https://", "");
- var cdnServerUrl = EnvironmentConfigs.Storage.CDNServerUrl.Replace("http://", "").Replace("https://", "");
- return value.Contains(cfsServerUrl) || value.Contains(cdnServerUrl);
- }
- return false;
- }
- }
- }
|