using AI.Common; using System; using System.Collections.Generic; using System.Runtime.Serialization; using System.Text; namespace AutoEFInferenceCalcLib { /// /// 单个心动周期相关信息 /// [DataContract] public struct CardiacCycleInfos { #region field private double _startTimeStamp; private double _endTimeStamp; private double _esTimeStamp; private double _edTimeStamp; private float _esVolume; private float _edVolume; #endregion #region public /// /// 心动周期开始的时间戳 /// public double StartTimeStamp { get => _startTimeStamp; set => _startTimeStamp = value; } /// /// 心动周期结束的时间戳 /// public double EndTimeStamp { get => _endTimeStamp; set => _endTimeStamp = value; } /// /// ES帧的时间戳 /// public double ESTimeStamp { get => _esTimeStamp; set => _esTimeStamp = value; } /// /// ED帧的时间戳 /// public double EDTimeStamp { get => _edTimeStamp; set => _edTimeStamp = value; } /// /// 当前心动周期内,收缩末期的左心室容积 /// public float ESVolume { get => _esVolume; set => _esVolume = value; } /// /// 当前心动周期内,舒张末期的左心室容积 /// public float EDVolume { get => _edVolume; set => _edVolume = value; } /// /// 空 /// public static readonly CardiacCycleInfos Empty = new CardiacCycleInfos(); /// /// 判断是否相等 /// /// /// public bool Equals(CardiacCycleInfos other) { return Equals(this, other); } /// /// 判断是否相等 /// /// /// public override bool Equals(object obj) { if (obj == null || !(obj is CardiacCycleInfos)) { return false; } CardiacCycleInfos info = (CardiacCycleInfos)obj; return Equals(this, info); } /// /// 判断是否相等 /// /// /// /// public static bool Equals(CardiacCycleInfos one, CardiacCycleInfos other) { return one.StartTimeStamp == other.StartTimeStamp && one.EndTimeStamp == other.EndTimeStamp && one.ESTimeStamp == other.ESTimeStamp && one.EDTimeStamp == other.EDTimeStamp && one.ESVolume == other.ESVolume && one.EDVolume == other.EDVolume; } /// /// 判断是否相等 /// /// /// /// public static bool operator ==(CardiacCycleInfos one, CardiacCycleInfos other) { return Equals(one, other); } /// /// 判断是否相等 /// /// /// /// public static bool operator !=(CardiacCycleInfos one, CardiacCycleInfos other) { return !Equals(one, other); } /// /// 构造函数 /// /// /// /// /// /// /// public CardiacCycleInfos(double startTimeStamp, double endTimeStamp, double esTimeStamp, double edTimeStamp, float esVolume, float edVolume) { _startTimeStamp = startTimeStamp; _endTimeStamp = endTimeStamp; _esTimeStamp = esTimeStamp; _edTimeStamp = edTimeStamp; _esVolume = esVolume; _edVolume = edVolume; } #endregion } /// /// 左心室容积测量的关键点 /// public struct LVVolumeMeasureMarks { #region field private Point2D _apexPoint; private Point2D[] _endPoints; private Point2D[] _slicePoints; private Point2D[] _controlPoints; #endregion #region public /// /// 左心室内轮廓心尖点,只有一个 /// public Point2D ApexPoint { get => _apexPoint; set => _apexPoint = value; } /// /// 左心室内轮廓末端点,有两个 /// public Point2D[] EndPoints { get => _endPoints; set => _endPoints = value; } /// /// 左心室内轮廓切片点 /// public Point2D[] SlicePoint { get => _slicePoints; set => _slicePoints = value; } /// /// 左心室内轮廓控制点 /// public Point2D[] ControlPoints { get => _controlPoints; set => _controlPoints = value; } /// /// 构造函数 /// /// /// /// /// public LVVolumeMeasureMarks(Point2D apexPoint, Point2D[] endPoints, Point2D[] slicePoints, Point2D[] controlPoints) { _apexPoint = apexPoint; _endPoints = endPoints; _slicePoints = slicePoints; _controlPoints = controlPoints; } public static readonly LVVolumeMeasureMarks Empty = new LVVolumeMeasureMarks(); /// /// 判断是否相等 /// /// /// public bool Equals(LVVolumeMeasureMarks other) { return Equals(this, other); } public override bool Equals(object obj) { if (obj == null || !(obj is LVVolumeMeasureMarks)) { return false; } LVVolumeMeasureMarks measureMarks = (LVVolumeMeasureMarks)obj; return Equals(this, measureMarks); } public static bool Equals(LVVolumeMeasureMarks one, LVVolumeMeasureMarks other) { if (one.ApexPoint != other.ApexPoint) { return false; } if (one.EndPoints != null && other.EndPoints == null || one.EndPoints == null && other.EndPoints != null || one.SlicePoint != null && other.SlicePoint == null || one.SlicePoint == null && other.SlicePoint != null || one.ControlPoints != null && one.ControlPoints == null || one.ControlPoints == null && other.ControlPoints != null) { return false; } if (one.EndPoints.Length != other.EndPoints.Length || one.SlicePoint.Length != other.EndPoints.Length || one.ControlPoints.Length != other.ControlPoints.Length) { return false; } for (int i = 0; i < one.EndPoints.Length; i++) { if (one.EndPoints[i] != other.EndPoints[i]) { return false; } } for (int i = 0; i < one.SlicePoint.Length; i++) { if (one.SlicePoint[i] != other.SlicePoint[i]) { return false; } } for (int i = 0; i < other.ControlPoints.Length; i++) { if (one.ControlPoints[i] != other.ControlPoints[i]) { return false; } } return true; } public static bool operator ==(LVVolumeMeasureMarks one, LVVolumeMeasureMarks other) { return Equals(one, other); } public static bool operator !=(LVVolumeMeasureMarks one, LVVolumeMeasureMarks other) { return !Equals(one, other); } #endregion } /// /// 单帧图像上的推理结果 /// public struct LVVolumeCalcResult { #region field private Point2D[] _contour; private double _volume; private float _score; private LVVolumeMeasureMarks _measureMarks; #endregion #region public /// /// 左心室内轮廓原始点 /// public Point2D[] Contour { get => _contour; set => _contour = value; } /// /// 左心室的容积值 /// public double Volume { get => _volume; set => _volume = value; } /// /// 心肌分割的得分 /// public float Score { get => _score; set => _score = value; } /// /// 左心室容积测量的关键点 /// public LVVolumeMeasureMarks MeasureMarks { get => _measureMarks; set => _measureMarks = value; } /// /// 构造函数 /// /// /// /// /// public LVVolumeCalcResult(Point2D[] contour, double Volume, float score, LVVolumeMeasureMarks measureMarks) { _contour = contour; _volume = Volume; _score = score; _measureMarks = measureMarks; } /// /// 空 /// public static readonly LVVolumeCalcResult Empty = new LVVolumeCalcResult(new Point2D[0], 0, 0, new LVVolumeMeasureMarks(new Point2D(0, 0), new Point2D[0], new Point2D[0], new Point2D[0])); public bool Equals(LVVolumeCalcResult other) { return Equals(this, other); } public override bool Equals(object obj) { if (obj == null || !(obj is LVVolumeCalcResult)) { return false; } LVVolumeCalcResult calcResult = (LVVolumeCalcResult)obj; return Equals(this, calcResult); } public static bool Equals(LVVolumeCalcResult one, LVVolumeCalcResult other) { if (one.Volume != other.Volume) { return false; } if (one.Score != other.Score) { return false; } if (one.Contour == null && other.Contour != null || one.Contour != null && other.Contour == null) { return false; } if (one.Contour.Length != other.Contour.Length) { return false; } if (one.MeasureMarks != other.MeasureMarks) { return false; } for (int i = 0; i < one.Contour.Length; i++) { if (one.Contour[i] != other.Contour[i]) { return false; } } return true; } public static bool operator ==(LVVolumeCalcResult one, LVVolumeCalcResult other) { return Equals(one, other); } public static bool operator !=(LVVolumeCalcResult one, LVVolumeCalcResult other) { return !Equals(one, other); } #endregion } [DataContract] [KnownType(typeof(CardiacCurveInfos))] public class CardiacCurveInfos { #region field private Dictionary _resultsPerImage; private int _bestCycleIndex; private CardiacCycleInfos[] _cardiacCycles; #endregion #region properties /// /// 每张图对应的左心室容积的计算结果 /// [DataMember] public Dictionary ResultPerImage { get => _resultsPerImage; set => _resultsPerImage = value; } /// /// 最好周期的Index /// [DataMember] public int BestCycleIndex { get => _bestCycleIndex; set => _bestCycleIndex = value; } /// /// 心动周期的信息 /// [DataMember] public CardiacCycleInfos[] CardiacCycles { get => _cardiacCycles; set => _cardiacCycles = value; } /// /// 构造函数 /// public CardiacCurveInfos() { _resultsPerImage = new Dictionary(); _bestCycleIndex = 0; _cardiacCycles = Array.Empty(); } /// /// 构造函数 /// /// /// /// public CardiacCurveInfos(Dictionary resultsPerImage, int bestCycleIndex, CardiacCycleInfos[] cardiacCycles) { _resultsPerImage = resultsPerImage; _bestCycleIndex = bestCycleIndex; _cardiacCycles = cardiacCycles; } /// /// 空 /// public static readonly CardiacCurveInfos Empty = new CardiacCurveInfos(); #endregion } }