123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750 |
- using System;
- using System.IO;
- using System.Collections.Generic;
- using System.Runtime.InteropServices;
- using AI.Common;
- using AI.Common.Log;
- using AI.Common.Tools;
- using static System.Net.Mime.MediaTypeNames;
- namespace AutoBlineCalculationLib
- {
- public class AutoBlineCalculation
- {
- #region internal
- /// <summary>
- /// cpp dll中模型分割结果的结构体
- /// </summary>
- [StructLayout(LayoutKind.Sequential)]
- internal struct StructCppIDetectedObject
- {
- public int label;
- public float confidence;
- public Rect boundingBox;
- public int pointNum;
- }
- /// <summary>
- /// cpp dll中扇形成像区域的相关信息
- /// </summary>
- [StructLayout(LayoutKind.Sequential)]
- internal struct StructCppSectorImageRegion
- {
- public float startRadius;
- public float startAngle;
- public float radiusSpan;
- public float angleSpan;
- public Point2D centerOfArc;
- public Point2D startUp;
- public Point2D startDown;
- public Point2D endUp;
- public Point2D endDown;
- public int contourPointsNum;
- }
- /// <summary>
- /// cpp dll中平行四边形成像区域的相关信息
- /// </summary>
- [StructLayout(LayoutKind.Sequential)]
- internal struct StructCppParallelogramImageRegion
- {
- public float horizontalSideLength;
- public float slantSideLength;
- public float angle;
- public Point2D center;
- public Point2D leftUp;
- public Point2D leftDown;
- public Point2D rightUp;
- public Point2D rightDown;
- public int contourPointsNum;
- }
- /// <summary>
- /// cpp dll中参与B线得分计算的一些特征的相关信息(凸阵探头)
- /// </summary>
- [StructLayout(LayoutKind.Sequential)]
- internal struct StructCppSectorBLineScoreFeatures
- {
- public int label;
- public float startRadius;
- public float startAngle;
- public float radiusSpan;
- public float angleSpan;
- public Point2D centerOfArc;
- }
- /// <summary>
- /// cpp dll中参与B线得分计算的一些特征的相关信息(线阵探头)
- /// </summary>
- [StructLayout(LayoutKind.Sequential)]
- internal struct StructCppParallelogramBLineScoreFeatures
- {
- public int label;
- public float horizontalSideLength;
- public float slantSideLength;
- public float angle;
- public Point2D center;
- }
- /// <summary>
- /// cpp dll中感兴趣区域的相关信息(凸阵探头)
- /// </summary>
- [StructLayout(LayoutKind.Sequential)]
- internal struct StructCppSectorRegionOfInterestInfo
- {
- public float startRadius;
- public float startAngle;
- public float radiusSpan;
- public float angleSpan;
- public Point2D centerOfArc;
- public Point2D startUp;
- public Point2D startDown;
- public Point2D endUp;
- public Point2D endDown;
- public float regionOfInterestScore;
- }
- /// <summary>
- /// cpp dll中感兴趣区域的相关信息(线阵探头)
- /// </summary>
- [StructLayout(LayoutKind.Sequential)]
- internal struct StructCppParallelogramRegionOfInterestInfo
- {
- public float horizontalSideLength;
- public float slantSideLength;
- public float angle;
- public Point2D center;
- public Point2D leftUp;
- public Point2D leftDown;
- public Point2D rightUp;
- public Point2D rightDown;
- public float regionOfInterestScore;
- }
-
- #endregion
- #region dllimport
- [DllImport(@"AutoBLineCalculationPostProcess", CallingConvention = CallingConvention.Cdecl)]
- [return: MarshalAs(UnmanagedType.I1)]
- internal static extern bool CalculateBLineScoreSectorImageRegion(IntPtr img_data, int channels, int imgW, int imgH,
- float cmPerPixel, StructCppSectorImageRegion imageRegion, IntPtr imageRegionContourPoints,
- int objectNum, StructCppIDetectedObject[] detectedObjects, IntPtr detectedObjectContourPoints,
- IntPtr bLineScoreFeatures, ref int featuresNum, StructCppSectorRegionOfInterestInfo sectorRegionOfInterestInfo, ref float regionOfInterestScore);
- [DllImport(@"AutoBLineCalculationPostProcess", CallingConvention = CallingConvention.Cdecl)]
- [return: MarshalAs(UnmanagedType.I1)]
- internal static extern bool CalculateBLineScoreParallelogramImageRegion(IntPtr img_data, int channels, int imgW, int imgH,
- float cmPerPixel, StructCppParallelogramImageRegion imageRegion, IntPtr imageRegionContourPoints,
- int objectNum, StructCppIDetectedObject[] detectedObjects, IntPtr detectedObjectContourPoints,
- IntPtr bLineScoreFeatures, ref int featuresNum, StructCppParallelogramRegionOfInterestInfo ParallelogramRegionOfInterestInfo, ref float regionOfInterestScore);
- #endregion
- #region field
- private IInferenceNetwork _inferNet;
- private static InferenceCore _inferenceCore = new InferenceCore();
- #endregion
- #region event
- /// <summary>
- /// 通知订阅者,推理过程中有log要记录
- /// </summary>
- public event EventHandler<LogEventArgs> NotifyLog;
- /// <summary>
- /// 通知订阅者,推理过程中发生了错误
- /// </summary>
- public event EventHandler<ErrorEventArgs> NotifyError;
- #endregion
- #region private funcs
- /// <summary>
- /// 单幅图的B线分割
- /// </summary>
- /// <param name="rawImg">rawImg格式图像</param>
- /// <param name="cropRect">裁图框区域</param>
- /// <returns></returns>
- private DetectedObject[] BlineModelProcess(RawImage rawImg)
- {
- List<DetectedObject> detected = new List<DetectedObject>();
- try
- {
- Rect cropRect = new Rect(0, 0, rawImg.Width, rawImg.Height);
- //对一张图进行推理
- InferenceNetworkInputImage inferInput = new InferenceNetworkInputImage(rawImg, cropRect);
- IDetectedObject[] inferResults = _inferNet.Process(inferInput);
- if (inferResults.Length == 0)
- {
- detected.Add(new DetectedObject());
- return detected.ToArray();
- }
- else
- {
- foreach (var obj in inferResults)
- {
- detected.Add(new DetectedObject(obj.Label, obj.Confidence, obj.BoundingBox, obj.Contours));
- }
- return detected.ToArray();
- }
- }
- catch (Exception excep)
- {
- NotifyError?.Invoke(this, new ErrorEventArgs(excep));
- detected.Add(new DetectedObject());
- return detected.ToArray();
- }
- }
- /// <summary>
- /// 统计模型分割结果
- /// 统计各个结果在超声图像区域下的相关信息
- /// 统计B线评分
- /// </summary>
- /// <param name="rawImg"></param>
- /// <param name="segResults"></param>
- /// <returns></returns>
- private BlineScoringResults BlineCalculation(RawImage image, DetectedObject[] segResults, float cmPerPixel, IUltrasoundImageRegion imageRegion,
- IUltrasoundImageRegion roiSectorOrParallelogram, BlineScoringResults allResults)
- {
- try
- {
- int imgWidth = image.Width;
- int imgHeight = image.Height;
- int channel = image.BytesPerPixel;
- // 取出所有检测到的组织结构,及对应的轮廓
- int objectNum = segResults.Length;
- List<Point2D> allContourPoints = new List<Point2D>();
- StructCppIDetectedObject[] detectedObjectStructs = new StructCppIDetectedObject[objectNum];
- for (int ni = 0; ni < objectNum; ni++)
- {
- detectedObjectStructs[ni].label = segResults[ni].Label;
- detectedObjectStructs[ni].confidence = segResults[ni].Confidence;
- detectedObjectStructs[ni].boundingBox = segResults[ni].BoundingBox;
- detectedObjectStructs[ni].pointNum = segResults[ni].Contours[0].Length;
- allContourPoints.AddRange(segResults[ni].Contours[0]);
- }
- // 获取指针
- GCHandle hObjectContour = GCHandle.Alloc(allContourPoints.ToArray(), GCHandleType.Pinned);
- IntPtr pObjectContour = hObjectContour.AddrOfPinnedObject();
- GCHandle hObjectImg = GCHandle.Alloc(image.DataBuffer, GCHandleType.Pinned);
- IntPtr pObjectImg = hObjectImg.AddrOfPinnedObject();
- // 可做B线评分的特征数组的最大尺寸,暂定为30
- int featuresNum = 30;
- // 取出超声成像区域
- List<Point2D> imageRegionContourPoints = new List<Point2D>();
- var regionType = imageRegion.GetType();
- float regionOfInterestScore = 0; //暂时赋值为0
- // 凸阵探头
- if (regionType == typeof(ConvexArrayUltrasoundImageRegion))
- {
- StructCppSectorBLineScoreFeatures[] features = new StructCppSectorBLineScoreFeatures[featuresNum];
- var sector = (Sector)((ConvexArrayUltrasoundImageRegion)imageRegion).Geometry;
- StructCppSectorImageRegion sectorImageRegion = new StructCppSectorImageRegion
- {
- startAngle = sector.StartAngle,
- startRadius = sector.StartRadius,
- angleSpan = sector.AngleSpan,
- radiusSpan = sector.RadiusSpan,
- centerOfArc = sector.CenterOfArc,
- startUp = sector.StartUp,
- endUp = sector.EndUp,
- startDown = sector.StartDown,
- endDown = sector.EndDown,
- contourPointsNum = sector.Contour.Points.Length,
- };
- // 获取感兴趣区域结构体的相关参数
- StructCppSectorRegionOfInterestInfo sectorRegionOfInterestInfo = new StructCppSectorRegionOfInterestInfo();
- var sectorROI = (Sector)((ConvexArrayUltrasoundImageRegion)roiSectorOrParallelogram).Geometry;
- sectorRegionOfInterestInfo.startRadius = sectorROI.StartRadius;
- sectorRegionOfInterestInfo.startAngle = sectorROI.StartAngle;
- sectorRegionOfInterestInfo.radiusSpan = sectorROI.RadiusSpan;
- sectorRegionOfInterestInfo.angleSpan = sectorROI.AngleSpan;
- sectorRegionOfInterestInfo.centerOfArc = sectorROI.CenterOfArc;
- sectorRegionOfInterestInfo.startUp = sectorROI.StartUp;
- sectorRegionOfInterestInfo.startDown = sectorROI.StartDown;
- sectorRegionOfInterestInfo.endUp = sectorROI.EndUp;
- sectorRegionOfInterestInfo.endDown = sectorROI.EndDown;
- sectorRegionOfInterestInfo.regionOfInterestScore = 0; // 暂定感兴趣区域得分为0,记为红色框
- imageRegionContourPoints.AddRange(sector.Contour.Points);
- GCHandle hImageRegionContour = GCHandle.Alloc(imageRegionContourPoints.ToArray(), GCHandleType.Pinned);
- IntPtr pImageRegionContour = hImageRegionContour.AddrOfPinnedObject();
- GCHandle hFeatures = GCHandle.Alloc(features, GCHandleType.Pinned);
- IntPtr pFeatures = hFeatures.AddrOfPinnedObject();
- var ret = CalculateBLineScoreSectorImageRegion(pObjectImg, channel, imgWidth, imgHeight, (float)cmPerPixel,
- sectorImageRegion, pImageRegionContour, objectNum, detectedObjectStructs, pObjectContour, pFeatures, ref featuresNum, sectorRegionOfInterestInfo, ref regionOfInterestScore);
- // 释放
- if (hObjectContour.IsAllocated)
- {
- hObjectContour.Free();
- }
- if (hObjectImg.IsAllocated)
- {
- hObjectImg.Free();
- }
- if (hImageRegionContour.IsAllocated)
- {
- hImageRegionContour.Free();
- }
- if (hFeatures.IsAllocated)
- {
- hFeatures.Free();
- }
- // 统计并保存分割结果、凸阵探头下超声成像区域相关信息、B线评分
- // 1、将分割模型得到的目标结果放置在定义好的结构体中
- BlineRecognizedObjectInfo[] recognizedObjects = new BlineRecognizedObjectInfo[segResults.Length];
- for (int ni = 0; ni < segResults.Length; ni++)
- {
- recognizedObjects[ni] = new BlineRecognizedObjectInfo((EnumBlineRecognizedObjectType)segResults[ni].Label,
- segResults[ni].Confidence, segResults[ni].Contours[0]);
- }
- // 2、将凸阵探头下的每条B线轮廓换算成需要的扇形信息并放置至BLineScoringInfo函数中
- BLineScoringInfo[] calculatedObjects = new BLineScoringInfo[featuresNum];
- for (int ni = 0; ni < featuresNum; ni++)
- {
- IUltrasoundImageRegion eachgeometry;
- var depthSpanInPixel = (int)features[ni].radiusSpan;
- var centerDepthInPixel = (int)features[ni].startRadius + depthSpanInPixel / 2;
- var imageWidthInPixel = 2 * (int)features[ni].centerOfArc.X;
- var scanMaxWidth = features[ni].angleSpan;
- var originToProbeSurfaceInPixel = features[ni].centerOfArc.Y / -(Math.Cos(MathHelper.DegreeToRadian(scanMaxWidth / 2)));
- var startAngle = features[ni].startAngle;
- var centerOfAngle = startAngle + scanMaxWidth / 2;
- var beamPosition = centerOfAngle - 270;
- var widthSpan = features[ni].angleSpan;
- var geoTest = new ConvexArrayUltrasoundImageRegion((int)originToProbeSurfaceInPixel, (int)imageWidthInPixel, (int)centerDepthInPixel, (int)depthSpanInPixel,
- (double)scanMaxWidth, (double)widthSpan, (double)beamPosition);
- eachgeometry = geoTest;
- // 保存每条B线轮廓换算后的扇形信息
- calculatedObjects[ni] = new BLineScoringInfo((EnumBlineScoreType)features[ni].label, eachgeometry);
- }
-
- // 3、计算单帧图像中总的B线得分
- int finalScore = CalculateBLineScore(calculatedObjects);
- // 4、更新感兴趣区域及对应得分
- RegionOfInterestInfo regionOfInterestInfo = new RegionOfInterestInfo();
- regionOfInterestInfo.UltrasoundRegionOfInterest = roiSectorOrParallelogram;
- regionOfInterestInfo.RegionOfInterestScore = regionOfInterestScore;
- // 5、保存所有结果
- allResults.BlineScore = finalScore;
- allResults.BlineScoringInfo = calculatedObjects;
- allResults.RecognizedObjects = recognizedObjects;
- allResults.RegionOfInterestInfo = regionOfInterestInfo;
- return allResults;
- }
- // 线阵探头
- else if (regionType == typeof(LinearArrayUltrasoundImageRegion))
- {
- StructCppParallelogramBLineScoreFeatures[] features = new StructCppParallelogramBLineScoreFeatures[featuresNum];
- var region = (LinearArrayUltrasoundImageRegion)imageRegion;
- StructCppParallelogramImageRegion parallelogramImageRegion = new StructCppParallelogramImageRegion();
- StructCppParallelogramRegionOfInterestInfo ParallelogramRegionOfInterestInfo = new StructCppParallelogramRegionOfInterestInfo();
- if (MathHelper.AlmostEqual(region.Steer, 0))
- {
- var rectangle = (Rectangle)(region.Geometry);
- parallelogramImageRegion = new StructCppParallelogramImageRegion
- {
- horizontalSideLength = rectangle.Width,
- slantSideLength = rectangle.Height,
- angle = 0,
- center = rectangle.Center,
- leftUp = rectangle.LeftUp,
- leftDown = rectangle.LeftDown,
- rightUp = rectangle.RightUp,
- rightDown = rectangle.RightDown,
- contourPointsNum = rectangle.Contour.Points.Length,
- };
- imageRegionContourPoints.AddRange(rectangle.Contour.Points);
- // 获取感兴趣区域结构体的相关参数
- var rectangleROI = (Rectangle)((LinearArrayUltrasoundImageRegion)roiSectorOrParallelogram).Geometry;
- ParallelogramRegionOfInterestInfo.horizontalSideLength = rectangleROI.Width;
- ParallelogramRegionOfInterestInfo.slantSideLength = rectangleROI.Height;
- ParallelogramRegionOfInterestInfo.angle = 0;
- ParallelogramRegionOfInterestInfo.center = rectangleROI.Center;
- ParallelogramRegionOfInterestInfo.leftUp = rectangleROI.LeftUp;
- ParallelogramRegionOfInterestInfo.leftDown = rectangleROI.LeftDown;
- ParallelogramRegionOfInterestInfo.rightUp = rectangleROI.RightUp;
- ParallelogramRegionOfInterestInfo.rightDown = rectangleROI.RightDown;
- ParallelogramRegionOfInterestInfo.regionOfInterestScore = 0; // 暂定感兴趣区域得分为0,记为红色框
- }
- else
- {
- var parallelogram = (Parallelogram)(region.Geometry);
- parallelogramImageRegion = new StructCppParallelogramImageRegion
- {
- horizontalSideLength = parallelogram.HorizontalSideLength,
- slantSideLength = parallelogram.SlantSideLength,
- angle = parallelogram.Angle,
- center = parallelogram.Center,
- leftUp = parallelogram.LeftUp,
- leftDown = parallelogram.LeftDown,
- rightUp = parallelogram.RightUp,
- rightDown = parallelogram.RightDown,
- contourPointsNum = parallelogram.Contour.Points.Length,
- };
- imageRegionContourPoints.AddRange(parallelogram.Contour.Points);
- // 获取感兴趣区域结构体的相关参数
- var parallelogramROI = (Parallelogram)((LinearArrayUltrasoundImageRegion)roiSectorOrParallelogram).Geometry;
- ParallelogramRegionOfInterestInfo.horizontalSideLength = parallelogramROI.HorizontalSideLength;
- ParallelogramRegionOfInterestInfo.slantSideLength = parallelogramROI.SlantSideLength;
- ParallelogramRegionOfInterestInfo.angle = parallelogramROI.Angle;
- ParallelogramRegionOfInterestInfo.center = parallelogramROI.Center;
- ParallelogramRegionOfInterestInfo.leftUp = parallelogramROI.LeftUp;
- ParallelogramRegionOfInterestInfo.leftDown = parallelogramROI.LeftDown;
- ParallelogramRegionOfInterestInfo.rightUp = parallelogramROI.RightUp;
- ParallelogramRegionOfInterestInfo.rightDown = parallelogramROI.RightDown;
- ParallelogramRegionOfInterestInfo.regionOfInterestScore = 0; // 暂定感兴趣区域得分为0,记为红色框
- }
- GCHandle hImageRegionContour = GCHandle.Alloc(imageRegionContourPoints.ToArray(), GCHandleType.Pinned);
- IntPtr pImageRegionContour = hImageRegionContour.AddrOfPinnedObject();
- GCHandle hFeatures = GCHandle.Alloc(features, GCHandleType.Pinned);
- IntPtr pFeatures = hFeatures.AddrOfPinnedObject();
- var ret = CalculateBLineScoreParallelogramImageRegion(pObjectImg, channel, imgWidth, imgHeight, (float)cmPerPixel,
- parallelogramImageRegion, pImageRegionContour, objectNum, detectedObjectStructs, pObjectContour, pFeatures, ref featuresNum, ParallelogramRegionOfInterestInfo, ref regionOfInterestScore);
- // 释放
- if (hObjectContour.IsAllocated)
- {
- hObjectContour.Free();
- }
- if (hObjectImg.IsAllocated)
- {
- hObjectImg.Free();
- }
- if (hImageRegionContour.IsAllocated)
- {
- hImageRegionContour.Free();
- }
- if (hFeatures.IsAllocated)
- {
- hFeatures.Free();
- }
- // 统计并保存分割结果、线阵探头下超声成像区域相关信息、B线评分
- // 1、将分割模型得到的目标结果放置在定义好的结构体中
- BlineRecognizedObjectInfo[] recognizedObjects = new BlineRecognizedObjectInfo[segResults.Length];
- for (int ni = 0; ni < segResults.Length; ni++)
- {
- recognizedObjects[ni] = new BlineRecognizedObjectInfo((EnumBlineRecognizedObjectType)segResults[ni].Label,
- segResults[ni].Confidence, segResults[ni].Contours[0]);
- }
- // 2、将线阵探头下的每条B线轮廓换算成需要的矩形(或是平行四边行)信息并放置至BLineScoringInfo函数中
- BLineScoringInfo[] calculatedObjects = new BLineScoringInfo[featuresNum];
- if (MathHelper.AlmostEqual(region.Steer, 0))
- {
- for (int ni = 0; ni < featuresNum; ni++)
- {
- IUltrasoundImageRegion eachgeometry;
- var featureNi = features[ni];
- var beamPositionInPixelLinear = featureNi.center.X;
- var centerDepthInPixelLinear = featureNi.center.Y;
- var widthSpanInPixelLinear = featureNi.horizontalSideLength;
- var depthSpanInPixelLinear = featureNi.slantSideLength;
- var steer = featureNi.angle;
- var featureRectangle = new LinearArrayUltrasoundImageRegion(centerDepthInPixelLinear, (int)depthSpanInPixelLinear, (int)widthSpanInPixelLinear, (int)beamPositionInPixelLinear, steer);
- eachgeometry = featureRectangle;
- // 保存每条B线轮廓换算后的扇形信息
- calculatedObjects[ni] = new BLineScoringInfo((EnumBlineScoreType)features[ni].label, eachgeometry);
- }
- //3、计算单帧图像中总的B线得分
- int finalScore = CalculateBLineScore(calculatedObjects);
- // 4、更新感兴趣区域及对应得分
- RegionOfInterestInfo regionOfInterestInfo = new RegionOfInterestInfo();
- regionOfInterestInfo.UltrasoundRegionOfInterest = roiSectorOrParallelogram;
- regionOfInterestInfo.RegionOfInterestScore = regionOfInterestScore;
- // 5、保存所有结果
- allResults.BlineScore = finalScore;
- allResults.BlineScoringInfo = calculatedObjects;
- allResults.RecognizedObjects = recognizedObjects;
- allResults.RegionOfInterestInfo = regionOfInterestInfo;
- return allResults;
- }
- else
- {
- for (int ni = 0; ni < featuresNum; ni++)
- {
- IUltrasoundImageRegion eachgeometry;
- var featureNi = features[ni];
- var beamPositionInPixelLinear = featureNi.center.X;
- var centerDepthInPixelLinear = featureNi.center.Y;
- var widthSpanInPixelLinear = featureNi.horizontalSideLength;
- var depthSpanInPixelLinear = featureNi.slantSideLength;
- var steer = featureNi.angle;
- var featureRectangle = new LinearArrayUltrasoundImageRegion(centerDepthInPixelLinear, (int)depthSpanInPixelLinear, (int)widthSpanInPixelLinear, (int)beamPositionInPixelLinear, steer);
- eachgeometry = featureRectangle;
- // 保存每条B线轮廓换算后的扇形信息
- calculatedObjects[ni] = new BLineScoringInfo((EnumBlineScoreType)features[ni].label, eachgeometry);
- }
- // 3、计算总的B线得分
- int finalScore = CalculateBLineScore(calculatedObjects);
- // 4、更新感兴趣区域及对应得分
- RegionOfInterestInfo regionOfInterestInfo = new RegionOfInterestInfo();
- regionOfInterestInfo.UltrasoundRegionOfInterest = roiSectorOrParallelogram;
- regionOfInterestInfo.RegionOfInterestScore = regionOfInterestScore;
- // 5、保存所有结果
- allResults.BlineScore = finalScore;
- allResults.BlineScoringInfo = calculatedObjects;
- allResults.RecognizedObjects = recognizedObjects;
- allResults.RegionOfInterestInfo = regionOfInterestInfo;
- return allResults;
- }
- }
- }
- catch (Exception excep)
- {
- NotifyError?.Invoke(this, new ErrorEventArgs(excep));
- }
- return BlineScoringResults.Empty;
- }
-
- /// <summary>
- /// 计算B线评分
- /// </summary>
- /// <param name="calculatedObjectss"></param>
- /// <returns></returns>
- private int CalculateBLineScore(BLineScoringInfo[] calculatedObjectss)
- {
- // 没有检测到可以计算得分的特征,则B线得分为0
- if (calculatedObjectss.Length <= 0)
- {
- return 0;
- }
- // 根据融合B线、孤立B线和肺实变的个数,计算得分
- int finalScore = 0;
- int isolatedBLineNum = 0;
- int fusionBLineNum = 0;
- int lungConsolidationNum = 0;
- for (int ni = 0; ni < calculatedObjectss.Length; ni++)
- {
- if (calculatedObjectss[ni].Type == EnumBlineScoreType.IsolatedBLine)
- {
- isolatedBLineNum += 1;
- }
- else if (calculatedObjectss[ni].Type == EnumBlineScoreType.FusionBLine)
- {
- fusionBLineNum += 1;
- }
- else if (calculatedObjectss[ni].Type == EnumBlineScoreType.LungConsolidation)
- {
- lungConsolidationNum += 1;
- }
- }
- if (fusionBLineNum == 0 && lungConsolidationNum == 0)
- {
- // 孤立BLine小于等于两条视为正常通气
- if (isolatedBLineNum <= 2)
- {
- finalScore = 0;
- }
- // 孤立BLine大于两条视为中度通气受损
- else
- {
- finalScore = 1;
- }
- }
- // 如果存在融合BLine,暂定不管有没有孤立BLine,都判定为严重肺通气受损(依据需求中的评分规则,后续根据实际情况可能会做调整)
- else if (fusionBLineNum > 0 && lungConsolidationNum == 0)
- {
- finalScore = 2;
- }
- // 只要肺实变存在,无论是否存在孤立BLine或融合BLine,均视为肺实变
- else if (lungConsolidationNum > 0)
- {
- finalScore = 3;
- }
- return finalScore;
- }
- #endregion
- #region public funcs
- /// <summary>
- /// 构造函数
- /// </summary>
- /// <param name="numCpu"></param>
- /// <param name="netDir"></param>
- public AutoBlineCalculation(int numCpu, string netDir)
- {
- try
- {
- _inferNet = new InferNetOnnxAutoBlineSeg();
- if (!_inferNet.ModelLoaded)
- {
- byte[] trainedNetwork =
- InferenceNetworkUtils.ReadNetworkDataFromFile(netDir, _inferNet.NetworkName,
- _inferNet.HashCode);
- // 设置inferCore的参数
- _inferenceCore.SetConfig(EnumInferCoreConfigKey.CPU_THREADS_NUM, numCpu.ToString(),
- EnumDeviceType.CPU);
- _inferNet.LoadNetwork(_inferenceCore, EnumDeviceType.CPU, trainedNetwork);
- }
- }
- catch (Exception excep)
- {
- throw new Exception("Failed at Loading network:" + excep);
- }
- }
- /// <summary>
- /// 计算单张图像中的B线数量和评分
- /// </summary>
- /// <param name="rawImg"></param>
- /// <param name="cmPerPixel"></param>
- /// <param name="imgRegion"></param>
- /// <returns></returns>
- public BlineScoringResults EvaluateOneImage(RawImage rawImg, float cmPerPixel, IUltrasoundImageRegion imgRegion)
- {
- if (rawImg.ColorType == EnumColorType.Gray16)
- {
- throw new ArgumentOutOfRangeException("ColorType", "The colorType of Gray16 is not supported for AutoBlineCalculation by now.");
- }
- if (rawImg.ColorType == EnumColorType.GrayF32)
- {
- throw new ArgumentOutOfRangeException("ColorType", "The colorType of GrayF32 is not supported for AutoBlineCalculation by now.");
- }
- RawImage imgRGB = rawImg;
- if (rawImg.ColorType != EnumColorType.Bgr)
- {
- imgRGB = rawImg.Clone(EnumColorType.Bgr);
- }
- // 模型分割结果
- DetectedObject[] netResults = BlineModelProcess(imgRGB);
- // 如果没有B线或肺实变,则B线得分为0,可以不用再做后续的处理
- bool hasBline = Array.Find(netResults, a => a.Label == 2) != null;
- bool hasLungConsolidation = Array.Find(netResults, a => a.Label == 4) != null;
- //定义单帧图中的所有结果
- BlineScoringResults allResults = new BlineScoringResults();
- // 计算感兴趣区域框
- IUltrasoundImageRegion roiSectorOrParallelogram;
- var regionType = imgRegion.GetType();
- if (regionType != typeof(ConvexArrayUltrasoundImageRegion) && regionType != typeof(LinearArrayUltrasoundImageRegion))
- {
- throw new ArgumentOutOfRangeException("imageRegion", "the expected type of imageRegion is 'ConvexArrayUltrasoundImageRegion' or 'LinearArrayUltrasoundImageRegion'");
- }
- // B线计算必须要有超声成像区域
- if (imgRegion == null)
- {
- throw new ArgumentException("no 'UltrasoundImageRegion' found for task 'BLineScore'.");
- }
- // 凸阵探头
- if (regionType == typeof(ConvexArrayUltrasoundImageRegion))
- {
- // 计算感兴趣区域超声成像参数
- var sector = (Sector)((ConvexArrayUltrasoundImageRegion)imgRegion).Geometry;
- var depthSpanInPixelROI = sector.RadiusSpan;
- var centerDepthInPixelROI = sector.StartRadius + depthSpanInPixelROI / 2;
- var imageWidthInPixelROI = 2 * sector.CenterOfArc.X;
- var scanMaxWidthROI = (sector.AngleSpan / 8) * 6;
- var originToProbeSurfaceInPixelROI = sector.CenterOfArc.Y / -(Math.Cos(MathHelper.DegreeToRadian(scanMaxWidthROI / 2)));
- var startAngleROI = sector.StartAngle + sector.AngleSpan / 8;
- var centerOfAngleROI = startAngleROI + scanMaxWidthROI / 2;
- var beamPositionROI = centerOfAngleROI - 270;
- var widthSpanROI = (sector.AngleSpan / 8) * 6;
- var sectorROI = new ConvexArrayUltrasoundImageRegion((int)originToProbeSurfaceInPixelROI, (int)imageWidthInPixelROI, (int)centerDepthInPixelROI, (int)depthSpanInPixelROI,
- (double)scanMaxWidthROI, (double)widthSpanROI, (double)beamPositionROI);
- roiSectorOrParallelogram = sectorROI;
- RegionOfInterestInfo regionOfInterestInfo = new RegionOfInterestInfo(0, roiSectorOrParallelogram);
- allResults.RegionOfInterestInfo = regionOfInterestInfo;
- if (!(hasBline || hasLungConsolidation))
- {
- return allResults;
- }
- // 检测到上述四个目标中的任意一个,则进一步统计B线数量并计算评分
- var calResults = BlineCalculation(imgRGB, netResults, cmPerPixel, imgRegion, roiSectorOrParallelogram, allResults);
- // 更新allResults
- allResults.BlineScore = calResults.BlineScore;
- allResults.RecognizedObjects = calResults.RecognizedObjects;
- allResults.BlineScoringInfo= calResults.BlineScoringInfo;
- allResults.RegionOfInterestInfo= calResults.RegionOfInterestInfo;
- return allResults;
- }
- else if (regionType == typeof(LinearArrayUltrasoundImageRegion))
- {
- var linearRegion = (LinearArrayUltrasoundImageRegion)imgRegion;
- RegionOfInterestInfo regionOfInterestInfo = new RegionOfInterestInfo(0, null);
- if (MathHelper.AlmostEqual(linearRegion.Steer, 0))
- {
- var reRectangle = (Rectangle)(linearRegion).Geometry;
- var centerDepthInPixelROI = reRectangle.LeftUp.Y+ reRectangle.Height / 2;
- //var centerDepthInPixelROI = reRectangle.Height/2;
- var depthSpanInPixelROI = reRectangle.Height;
- var widthSpanInPixelROI = (reRectangle.Width / 8) * 6;
- var beamPositionInPixelROI = reRectangle.LeftUp.X+ reRectangle.Width/2;
- var steerROI = 0;
- var reRectangleROI = new LinearArrayUltrasoundImageRegion((int)centerDepthInPixelROI, (int)depthSpanInPixelROI, (int)widthSpanInPixelROI, (int)beamPositionInPixelROI, steerROI);
- roiSectorOrParallelogram = reRectangleROI;
- RegionOfInterestInfo roiParallelogram = new RegionOfInterestInfo(0, roiSectorOrParallelogram);
- allResults.RegionOfInterestInfo = roiParallelogram;
- if (!(hasBline || hasLungConsolidation))
- {
- return allResults;
- }
- // 检测到上述四个目标中的任意一个,则进一步统计B线数量并计算评分
- var calResults = BlineCalculation(imgRGB, netResults, cmPerPixel, imgRegion, roiSectorOrParallelogram, allResults);
- // 更新allResults
- allResults.BlineScore = calResults.BlineScore;
- allResults.RecognizedObjects = calResults.RecognizedObjects;
- allResults.BlineScoringInfo = calResults.BlineScoringInfo;
- allResults.RegionOfInterestInfo = calResults.RegionOfInterestInfo;
- return allResults;
- }
- else
- {
- var reParallelogram = (Parallelogram)(linearRegion).Geometry;
- var beamPositionInPixelROI = ((reParallelogram.Center.X / 8) * 6) / 2;
- var centerDepthInPixelROI = reParallelogram.Center.Y;
- var widthSpanInPixelROI = (int)(reParallelogram.HorizontalSideLength / 8 * 6);
- var depthSpanInPixelROI = (int)reParallelogram.SlantSideLength;
- var steerROI = reParallelogram.Angle;
- var reRectangleROI = new LinearArrayUltrasoundImageRegion((int)centerDepthInPixelROI, (int)depthSpanInPixelROI, (int)widthSpanInPixelROI, (int)beamPositionInPixelROI, steerROI);
- roiSectorOrParallelogram = reRectangleROI;
- RegionOfInterestInfo roiParallelogram = new RegionOfInterestInfo(0, roiSectorOrParallelogram);
- allResults.RegionOfInterestInfo = regionOfInterestInfo;
- if (!(hasBline || hasLungConsolidation))
- {
- return allResults;
- }
- // 检测到上述四个目标中的任意一个,则进一步统计B线数量并计算评分
- var calResults = BlineCalculation(imgRGB, netResults, cmPerPixel, imgRegion, roiSectorOrParallelogram, allResults);
- // 更新allResults
- allResults.BlineScore = calResults.BlineScore;
- allResults.RecognizedObjects = calResults.RecognizedObjects;
- allResults.BlineScoringInfo = calResults.BlineScoringInfo;
- allResults.RegionOfInterestInfo = calResults.RegionOfInterestInfo;
- return allResults;
- }
- }
- else
- {
- return allResults;
- }
- }
- /// <summary>
- /// 销毁
- /// </summary>
- public void Dispose()
- {
- DoDispose();
- GC.SuppressFinalize(this);
- }
- #endregion
- #region private funcs
- /// <summary>
- /// 主动销毁
- /// </summary>
- private void DoDispose()
- {
- _inferNet?.Dispose();
- _inferNet = null;
- }
- #endregion
- }
- }
|