Ejemplo n.º 1
0
        public static DVH CalculateSDF_DVH(StructureMeta sm, DoseMatrix dm)
        {
            var cropDM = dm.Clone();

            cropDM.CropMatrixToStructure(sm, 2);
            // cropDM.ShowAllSlices();
            var sdf = sm.CalculateSDFMatrix(cropDM);

            cropDM.Resample(cropDM.XRes / 3, cropDM.YRes / 3, cropDM.ZRes / 3);
            sdf.Resample(sdf.XRes / 3, sdf.YRes / 3, sdf.ZRes / 3);

            var maxDose  = cropDM.MaxDose;
            var voxelCC  = cropDM.XRes / 10 * cropDM.YRes / 10 * cropDM.ZRes / 10;
            var doseUnit = dm.DoseUnit == DoseUnit.ABSOLUTE ? "Gy" : "%";
            var dvh      = new DVH(maxDose, voxelCC, doseUnit);

            var vol = 0.0;

            for (int z = 0; z < cropDM.DimensionZ; z++)
            {
                var zPos     = cropDM.ImageToPatientTx(new Core.Helpers.Vector3(0, 0, z)).Z;
                var contours = new SliceContourMeta[] { sdf.FindStructureContour(zPos) };
                vol += contours.Sum(c => c.CalculateArea()) * cropDM.ZRes;
                CalculateContoursDVH(contours, cropDM, dvh);
            }
            dvh.Volume = vol;

            return(dvh);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Recursive method that takes the largest contour and an array of smaller contours to
        /// place smaller contours which are inside the largest contour into the child list
        /// for area calculations
        /// </summary>
        /// <param name="largerContour">the large contour possibly containing smaller contours</param>
        /// <param name="smallerContours">the list of smaller contours</param>
        public static void OrganizeIntoChildren(SliceContourMeta largerContour, IEnumerable <SliceContourMeta> smallerContours)
        {
            if (!smallerContours.Any())
            {
                return;
            }

            foreach (var smaller in smallerContours)
            {
                if (largerContour.CompletelyContains(smaller))
                {
                    OrganizeIntoChildren(smaller, smallerContours.Where(s => s != smaller));
                    largerContour.Children.Add(smaller);
                }
            }
        }
Ejemplo n.º 3
0
        public static SliceContourMeta FindZeroLevelContours(this Mat mat, Func <Vector3, Vector3> imageToPatientFunc, int z)
        {
            var zPos  = imageToPatientFunc(new Vector3(0, 0, z)).Z;
            var meta  = new SliceContourMeta();
            var child = new SliceContourMeta();
            var level = new IsodoseLevel()
            {
                Value = 0, Color = new Scalar(255)
            };

            Point[][]        ctrs;
            HierarchyIndex[] hi;
            var thresh = mat.Threshold(level.Value, 255, ThresholdTypes.Binary);

            thresh = thresh.WindowAndLevel(128, 256);
            thresh.FindContours(out ctrs, out hi, RetrievalModes.CComp, ContourApproximationModes.ApproxSimple);
            for (int i = 0; i < hi.Length; i++)
            {
                var contour = ctrs[i];
                if (hi[i].Parent == -1)
                {
                    contour.ToList().ForEach(c =>
                    {
                        var pos = imageToPatientFunc(new Vector3(c.X, c.Y, 1));
                        pos.Z   = zPos;
                        meta.AddPoint(new Point3f((float)pos.X, (float)pos.Y, (float)pos.Z));
                    });
                }
                if (hi[i].Parent != -1)
                {
                    contour.ToList().ForEach(c =>
                    {
                        var pos = imageToPatientFunc(new Vector3(c.X, c.Y, 1));
                        pos.Z   = zPos;
                        child.AddPoint(new Point3f((float)pos.X, (float)pos.Y, (float)pos.Z));
                    });
                }
            }
            if (child.ContourPoints.Any())
            {
                meta.Children.Add(child);
            }
            thresh.Dispose();
            return(meta);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Finds contours on StructureMeta model (1 inside, -1 outsize, 0 boundry)
        /// </summary>
        /// <param name="mat"></param>
        /// <returns></returns>
        public static SliceContourMeta FindStructureContour(this Matrix model, double zPos)
        {
            var contourSlice = model.GetZPlane(zPos);
            var meta         = new SliceContourMeta();
            var child        = new SliceContourMeta();

            Point[][]        ctrs;
            HierarchyIndex[] hi;
            var thresh = contourSlice.Threshold(0, 255, ThresholdTypes.Binary).WindowAndLevel(128, 255);

            //Cv2.ImShow("Threshold", thresh);
            //Cv2.WaitKey();
            thresh.FindContours(out ctrs, out hi, RetrievalModes.CComp, ContourApproximationModes.ApproxNone);
            for (int i = 0; i < hi.Length; i++)
            {
                var contour = ctrs[i];
                if (hi[i].Parent == -1)
                {
                    contour.ToList().ForEach(c =>
                    {
                        var pos = model.ImageToPatientTx(new Vector3(c.X, c.Y, 1));
                        pos.Z   = zPos;
                        meta.AddPoint(new Point3f((float)pos.X, (float)pos.Y, (float)pos.Z));
                    });
                }
                if (hi[i].Parent != -1)
                {
                    contour.ToList().ForEach(c =>
                    {
                        var pos = model.ImageToPatientTx(new Vector3(c.X, c.Y, 1));
                        pos.Z   = zPos;
                        child.AddPoint(new Point3f((float)pos.X, (float)pos.Y, (float)pos.Z));
                    });
                }
            }
            if (child.ContourPoints.Any())
            {
                meta.Children.Add(child);
            }
            contourSlice.Dispose();
            thresh.Dispose();
            return(meta);
        }
Ejemplo n.º 5
0
        public static StructureMeta[] Find2DIsodoseLines(this Matrix matrix, params IsodoseLevel[] levels)
        {
            List <StructureMeta> metas = new List <StructureMeta>();

            foreach (var level in levels)
            {
                var meta = new StructureMeta()
                {
                    StructureId   = level.Value.ToString(),
                    StructureName = level.Value.ToString()
                };

                meta.Color = level.Color;

                for (int z = 0; z < matrix.DimensionZ; z++)
                {
                    using (var mat = matrix.GetZPlaneBySlice(z))
                    {
                        var ctrs = mat.Find2DIsodoseLine(level);
                        if (ctrs.Any())
                        {
                            foreach (var contour in ctrs)
                            {
                                var allPoints = new Vec4f[contour.Length];
                                var points    = contour.Select(c => new Vec4f(c.X, c.Y, z, 1));
                                using (var pointMat = new Mat <float>(new[] { contour.Length }, points.ToArray()))
                                {
                                    var txPointMat = pointMat.Transform(matrix.PatientTransformMatrix);
                                    txPointMat.GetArray(out allPoints);
                                }
                                var sliceContour = new SliceContourMeta();
                                var points3D     = allPoints.Select(a => new Point3f(a.Item0, a.Item1, a.Item2)).ToList();
                                points3D.ForEach(sliceContour.AddPoint);
                                meta.SliceContours.Add(sliceContour);
                            }
                        }
                    }
                }
                metas.Add(meta);
            }
            return(metas.ToArray());
        }
Ejemplo n.º 6
0
        public static StructureSetMeta ParseDICOM(string file)
        {
            var sm  = new StructureSetMeta();
            var dcm = DICOMObject.Read(file);
            var sel = dcm.GetSelector();

            var metas = sel.StructureSetROISequence.Items.Select(i =>
            {
                var meta         = new StructureMeta();
                meta.StructureId = i.GetSelector().ROIName?.Data;
                meta.ROINumber   = i.GetSelector().ROINumber.Data;
                return(meta);
            });

            foreach (var meta in metas)
            {
                try
                {
                    var comatch = sel.ROIContourSequence.Items.FirstOrDefault(i => i.GetSelector().ReferencedROINumber.Data == meta.ROINumber);
                    var romatch = sel.RTROIObservationsSequence.Items.FirstOrDefault(i => i.GetSelector().ReferencedROINumber.Data == meta.ROINumber);

                    var colorValues = comatch.GetSelector().ROIDisplayColor.Data_;
                    var color       = new Vec3b((byte)colorValues[0], (byte)colorValues[1], (byte)colorValues[2]);
                    var dicomType   = romatch.GetSelector().RTROIInterpretedType.Data;
                    var name        = romatch.GetSelector().ROIObservationLabel.Data;
                    meta.StructureName = name;
                    meta.Color         = new Scalar(colorValues[0], colorValues[1], colorValues[2]);

                    var hasContours = comatch.GetSelector().ContourSequence != null;
                    if (!hasContours)
                    {
                        continue;
                    }

                    //HAS CONTOURS - SET COLOR BYTES IN MATRIX
                    foreach (var slice in comatch.GetSelector().ContourSequence.Items)
                    {
                        var contours = slice.GetSelector().ContourData.Data_;
                        if (contours.Count % 3 != 0)
                        {
                            _logger.LogWarning($"Slice for structure {meta.StructureId} has {contours.Count} contour points. Not divisible by 3! Can't process."); continue;
                        }
                        try
                        {
                            var contour = new SliceContourMeta();
                            for (int i = 0; i < contours.Count; i += 3)
                            {
                                var contourPt = new OpenCvSharp.Point3f((float)contours[i + 0], (float)contours[i + 1], (float)contours[i + 2]);
                                contour.AddPoint(contourPt);
                            }
                            meta.SliceContours.Add(contour);
                            meta.DICOMType = dicomType;
                        }
                        catch (Exception e)
                        {
                            _logger.LogError(e.ToString());
                        }
                    }

                    //OrganizeContours - contours containing other contours (holes and fills) will be organized
                    //into children. All other contours are outermost contours and not children of any other
                    var slices = meta.SliceContours.GroupBy(s => s.Z).ToList();
                    foreach (var slice in slices)
                    {
                        var sliceContours = slice.OrderByDescending(s => s.CalculateArea()).ToList();
                        ContourHelper.OrganizeIntoChildren(sliceContours[0], sliceContours.Skip(1));
                    }
                    sm.Structures.Add(meta.StructureId, meta);
                }
                catch (Exception e)
                {
                    _logger.LogError(e, $"Could not add structure {meta.StructureId}");
                }
            }
            return(sm);
        }