|
@@ -162,7 +162,7 @@ namespace WingAIDiagnosisService.Service
|
|
|
var resultData = new DiagnosisImageResult();
|
|
|
if (DiagnosisHelper.IsCarotid(imageData))
|
|
|
{
|
|
|
- if (_isCarotidOn && imageData.ImageCount > DiagnosisHelper.CarotidMinImageCounts)
|
|
|
+ if (_isCarotidOn)
|
|
|
{
|
|
|
//颈动脉
|
|
|
var result = await CarotidDiagnosis(imageData);
|
|
@@ -444,17 +444,47 @@ namespace WingAIDiagnosisService.Service
|
|
|
/// <show>false</show>
|
|
|
public async Task<DiagnosisReportResult> DiagnosisReportAsync(DiagnosisReportRequest request)
|
|
|
{
|
|
|
+ var disgnosisReportResult = new DiagnosisReportResult();
|
|
|
try
|
|
|
{
|
|
|
- if (request.Organ == DiagnosisOrganEnum.CarotidArtery)
|
|
|
+ var is3DCarotid = false;
|
|
|
+ if (request.Organ == DiagnosisOrganEnum.CarotidArtery && is3DCarotid)
|
|
|
{
|
|
|
var result = await GetCarotidAIMeasureResult(request);
|
|
|
return result;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- var manager = await CreateDiagnosisManagerAsync(request);
|
|
|
- var reportPerImages = manager.GetReportResults();
|
|
|
+ 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;
|
|
|
+ if (leftRemedicals.Any())
|
|
|
+ {
|
|
|
+ var managerLeft = await CreateDiagnosisManagerAsync(new DiagnosisReportRequest { Organ = request.Organ, RemedicalList = leftRemedicals });
|
|
|
+ var perImages = managerLeft.GetReportResults();
|
|
|
+ leftRemedicalCode = perImages.FirstOrDefault()?.RemedicalCode;
|
|
|
+ reportPerImages.AddRange(perImages);
|
|
|
+ }
|
|
|
+ disgnosisReportResult.CarotidItems.AddRange(GetCarotidLeftReportItems(leftRemedicals.FirstOrDefault(x => x.RemedicalCode == leftRemedicalCode)));
|
|
|
+
|
|
|
+ var rightRemedicals = request.RemedicalList.Where(x => x.CarotidResult.CarotidScanType == CarotidScanTypeEnum.CarotidRight)?.ToList() ?? new List<DiagnosisRemicalDTO>();
|
|
|
+ var rightRemedicalCode = string.Empty;
|
|
|
+ if (rightRemedicals.Any())
|
|
|
+ {
|
|
|
+ var managerRight = await CreateDiagnosisManagerAsync(new DiagnosisReportRequest { Organ = request.Organ, RemedicalList = rightRemedicals });
|
|
|
+ var perImages = managerRight.GetReportResults();
|
|
|
+ rightRemedicalCode = perImages.FirstOrDefault()?.RemedicalCode;
|
|
|
+ reportPerImages.AddRange(perImages);
|
|
|
+ }
|
|
|
+ disgnosisReportResult.CarotidItems.AddRange(GetCarotidRightReportItems(rightRemedicals.FirstOrDefault(x => x.RemedicalCode == rightRemedicalCode)));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ var manager = await CreateDiagnosisManagerAsync(request);
|
|
|
+ reportPerImages = manager.GetReportResults();
|
|
|
+ }
|
|
|
var diagnosisConclusion = GetDiagnosisConclusion(reportPerImages);
|
|
|
var diagnosisOrgans = GetDiagnosisOrgans(reportPerImages);
|
|
|
|
|
@@ -480,18 +510,167 @@ namespace WingAIDiagnosisService.Service
|
|
|
perImageResult.DiagnosisOrgans = organs;
|
|
|
diagnosisResult.Add(perImageResult);
|
|
|
}
|
|
|
- return new DiagnosisReportResult
|
|
|
- {
|
|
|
- DiagnosisConclusion = (DiagnosisConclusionEnum)diagnosisConclusion,
|
|
|
- DiagnosisResult = diagnosisResult,
|
|
|
- };
|
|
|
+ disgnosisReportResult.DiagnosisConclusion = (DiagnosisConclusionEnum)diagnosisConclusion;
|
|
|
+ disgnosisReportResult.DiagnosisResult = diagnosisResult;
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
Logger.WriteLineWarn($"AIService DiagnosisReport err, {ex}");
|
|
|
}
|
|
|
- return new DiagnosisReportResult();
|
|
|
+ return disgnosisReportResult;
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<DataItemDTO> GetCarotidLeftReportItems(DiagnosisRemicalDTO leftData)
|
|
|
+ {
|
|
|
+ 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 = FormatterPlaceholder2($"NoPlaque2") });
|
|
|
+ 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);
|
|
|
+ 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 = 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 * 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") });
|
|
|
+ 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)
|
|
|
+ {
|
|
|
+ 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 = FormatterPlaceholder2($"NoPlaque2") });
|
|
|
+ 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);
|
|
|
+ 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 = 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 * 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") });
|
|
|
+ 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>
|
|
@@ -987,10 +1166,11 @@ namespace WingAIDiagnosisService.Service
|
|
|
return carotidResultInfos;
|
|
|
}
|
|
|
|
|
|
- private Tuple<WingInterfaceLibrary.DTO.Comment.AIDetectedObject, int> GetReportDetectedObject(List<WingInterfaceLibrary.DTO.Comment.AIDiagnosisResultPerOrgan> carotidResultInfos)
|
|
|
+ private Tuple<WingInterfaceLibrary.DTO.Comment.AIDetectedObject, int, string> GetReportDetectedObject(List<WingInterfaceLibrary.DTO.Comment.AIDiagnosisResultPerOrgan> carotidResultInfos)
|
|
|
{
|
|
|
WingInterfaceLibrary.DTO.Comment.AIDetectedObject detectedObject = null;
|
|
|
var maxArea = 0;
|
|
|
+ var maxAreaString = string.Empty;
|
|
|
foreach (var organInfo in carotidResultInfos)
|
|
|
{
|
|
|
var plaqueDetectedObjects = organInfo.DetectedObjects.Where(x => x.Label == 1);
|
|
@@ -1009,11 +1189,12 @@ namespace WingAIDiagnosisService.Service
|
|
|
{
|
|
|
detectedObject = dob;
|
|
|
maxArea = currArea;
|
|
|
+ maxAreaString = $"{Math.Round(diagnosisLesionSize.VerticalLengthInPixel * 0.1, 2)} × {Math.Round(diagnosisLesionSize.HorizontalLengthInPixel * 0.1, 2)}";
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- return new Tuple<WingInterfaceLibrary.DTO.Comment.AIDetectedObject, int>(detectedObject, maxArea);
|
|
|
+ return new Tuple<WingInterfaceLibrary.DTO.Comment.AIDetectedObject, int, string>(detectedObject, maxArea, maxAreaString);
|
|
|
}
|
|
|
|
|
|
private WingInterfaceLibrary.DTO.Comment.AIDiagnosisDescription GetDescription(WingInterfaceLibrary.DTO.Comment.AIDetectedObject detectedObject, DiagnosisDescriptionEnum descriptionType)
|
|
@@ -1052,6 +1233,8 @@ namespace WingAIDiagnosisService.Service
|
|
|
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()}");
|
|
|
}
|
|
@@ -1067,6 +1250,14 @@ namespace WingAIDiagnosisService.Service
|
|
|
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,
|
|
|
+ };
|
|
|
+ }
|
|
|
if (resampleResult.ResampleErrorCode == ResampleErrorCode.Success)
|
|
|
{
|
|
|
var carotidAIImageTokens = new List<CarotidAIImage>();
|
|
@@ -1311,6 +1502,11 @@ namespace WingAIDiagnosisService.Service
|
|
|
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))
|
|
|
{
|