public VolumeSliceArgs(int rows, int columns,
		                       float rowSpacing, float columnSpacing,
		                       Vector3D rowOrientationPatient,
		                       Vector3D columnOrientationPatient,
		                       float sliceThickness, int subsamples,
		                       VolumeInterpolationMode interpolation,
		                       VolumeProjectionMode projection)
		{
			Platform.CheckPositive(rows, "rows");
			Platform.CheckPositive(columns, "columns");
			Platform.CheckPositive(rowSpacing, "rowSpacing");
			Platform.CheckPositive(columnSpacing, "columnSpacing");
			Platform.CheckPositive(sliceThickness, "sliceThickness");
			Platform.CheckForNullReference(rowOrientationPatient, "rowOrientationPatient");
			Platform.CheckForNullReference(columnOrientationPatient, "columnOrientationPatient");

			_rows = rows;
			_columns = columns;
			_rowSpacing = rowSpacing;
			_columnSpacing = columnSpacing;
			_rowOrientationPatient = rowOrientationPatient.Normalize();
			_columnOrientationPatient = columnOrientationPatient.Normalize();
			_sliceThickness = sliceThickness;
			_subsamples = subsamples;
			_interpolation = interpolation;
			_projection = projection;
		}
        public VolumeSliceArgs(int rows, int columns,
                               float rowSpacing, float columnSpacing,
                               Vector3D rowOrientationPatient,
                               Vector3D columnOrientationPatient,
                               float sliceThickness, int subsamples,
                               VolumeInterpolationMode interpolation,
                               VolumeProjectionMode projection)
        {
            try
            {
                Platform.CheckPositive(rows, "rows");
                Platform.CheckPositive(columns, "columns");
            }
            catch (ExtensionException ex)
            {
                Platform.Log(LogLevel.Error, rows);
            }

            Platform.CheckPositive(rowSpacing, "rowSpacing");
            Platform.CheckPositive(columnSpacing, "columnSpacing");
            Platform.CheckPositive(sliceThickness, "sliceThickness");
            Platform.CheckForNullReference(rowOrientationPatient, "rowOrientationPatient");
            Platform.CheckForNullReference(columnOrientationPatient, "columnOrientationPatient");

            _rows                     = rows;
            _columns                  = columns;
            _rowSpacing               = rowSpacing;
            _columnSpacing            = columnSpacing;
            _rowOrientationPatient    = rowOrientationPatient.Normalize();
            _columnOrientationPatient = columnOrientationPatient.Normalize();
            _sliceThickness           = sliceThickness;
            _subsamples               = subsamples;
            _interpolation            = interpolation;
            _projection               = projection;
        }
		public static void AggregateSlabIntensity(VolumeProjectionMode mode, IntPtr pSlabData, byte[] pixelData, int subsamples, int subsamplePixels, int bytesPerPixel, bool signed)
		{
			switch (mode)
			{
				case VolumeProjectionMode.Maximum:
					AggregateSlabMaximumIntensity(pSlabData, pixelData, subsamples, subsamplePixels, bytesPerPixel, signed);
					return;
				case VolumeProjectionMode.Minimum:
					AggregateSlabMinimumIntensity(pSlabData, pixelData, subsamples, subsamplePixels, bytesPerPixel, signed);
					return;
				case VolumeProjectionMode.Average:
				default:
					AggregateSlabAverageIntensity(pSlabData, pixelData, subsamples, subsamplePixels, bytesPerPixel, signed);
					return;
			}
		}
Exemple #4
0
        public static void AggregateSlabIntensity(VolumeProjectionMode mode, IntPtr pSlabData, byte[] pixelData, int subsamples, int subsamplePixels, int bytesPerPixel, bool signed)
        {
            switch (mode)
            {
            case VolumeProjectionMode.Maximum:
                AggregateSlabMaximumIntensity(pSlabData, pixelData, subsamples, subsamplePixels, bytesPerPixel, signed);
                return;

            case VolumeProjectionMode.Minimum:
                AggregateSlabMinimumIntensity(pSlabData, pixelData, subsamples, subsamplePixels, bytesPerPixel, signed);
                return;

            case VolumeProjectionMode.Average:
            default:
                AggregateSlabAverageIntensity(pSlabData, pixelData, subsamples, subsamplePixels, bytesPerPixel, signed);
                return;
            }
        }
Exemple #5
0
        /// <summary>
        /// Gets the pixel data representing a thick slice (a.k.a. slab) of the volume.
        /// </summary>
        private static byte[] GetSlabPixelData(IVolumeReference volumeReference, Matrix resliceAxes, Vector3D stackOrientation, int rows, int columns, int subsamples, float rowSpacing, float columnSpacing, float sliceThickness, VolumeInterpolationMode interpolation, VolumeProjectionMode projection)
        {
            if (subsamples == 0)
            {
                return(GetSlicePixelData(volumeReference, resliceAxes, rows, columns, rowSpacing, columnSpacing, interpolation));
            }
            var subsampleSpacing = sliceThickness / (subsamples - 1);

            using (var reslicer = new vtkImageReslice())
                using (var resliceAxesMatrix = new vtkMatrix4x4())
                    using (var executive = reslicer.GetExecutive())
                        using (var volume = volumeReference.Volume.CreateVtkVolumeHandle())
                        {
                            // update the reslice axes matrix with the values from the slicing orientation
                            resliceAxesMatrix.SetElements(resliceAxes);

                            // determine offset for start of slab (we centre the slab on the requested slice position, as DICOM defines "image position (patient)" to be centre of the thick slice)
                            var slabOffset = volumeReference.RotateToVolumeOrientation(-sliceThickness / 2f * stackOrientation) + new Vector3D(resliceAxes[0, 3], resliceAxes[1, 3], resliceAxes[2, 3]);
                            resliceAxesMatrix.SetElement(0, 3, slabOffset.X);
                            resliceAxesMatrix.SetElement(1, 3, slabOffset.Y);
                            resliceAxesMatrix.SetElement(2, 3, slabOffset.Z);

                            // register for errors on the reslicer
                            reslicer.RegisterVtkErrorEvents();

                            // set input to the volume
                            reslicer.SetInput(volume.vtkImageData);
                            reslicer.SetInformationInput(volume.vtkImageData);

                            // instruct reslicer to output a 3D slab volume
                            reslicer.SetOutputDimensionality(3);

                            // use the volume's padding value for all pixels that are outside the volume
                            reslicer.SetBackgroundLevel(volumeReference.PaddingValue);

                            // ensure the slicer outputs at our desired spacing
                            reslicer.SetOutputSpacing(columnSpacing, rowSpacing, subsampleSpacing);

                            // set the reslice axes
                            reslicer.SetResliceAxes(resliceAxesMatrix);

                            // clamp the output based on the slice extent
                            reslicer.SetOutputExtent(0, columns - 1, 0, rows - 1, 0, subsamples - 1);

                            // set the output origin to the slice through-point (output image will be centered on this location)
                            // VTK output origin is derived from the center image being 0,0
                            reslicer.SetOutputOrigin(-columns * columnSpacing / 2, -rows * rowSpacing / 2, 0);

                            // select the requested interpolation mode
                            switch (interpolation)
                            {
                            case VolumeInterpolationMode.NearestNeighbor:
                                reslicer.SetInterpolationModeToNearestNeighbor();
                                break;

                            case VolumeInterpolationMode.Linear:
                                reslicer.SetInterpolationModeToLinear();
                                break;

                            case VolumeInterpolationMode.Cubic:
                                reslicer.SetInterpolationModeToCubic();
                                break;
                            }

                            // select the requested slab projection mode
                            Action <IntPtr, byte[], int, int, int, bool> slabAggregator;
                            switch (projection)
                            {
                            case VolumeProjectionMode.Maximum:
                                slabAggregator = SlabProjection.AggregateSlabMaximumIntensity;
                                break;

                            case VolumeProjectionMode.Minimum:
                                slabAggregator = SlabProjection.AggregateSlabMinimumIntensity;
                                break;

                            case VolumeProjectionMode.Average:
                            default:
                                slabAggregator = SlabProjection.AggregateSlabAverageIntensity;
                                break;
                            }

                            // register for errors on the reslicer executive
                            executive.RegisterVtkErrorEvents();
                            executive.Update();

                            // get the slice output
                            using (var imageData = reslicer.GetOutput())
                            {
                                var pixelData = SlabVtkImageData(imageData, slabAggregator, volumeReference.BitsPerVoxel, volumeReference.Signed);
                                imageData.ReleaseData();
                                return(pixelData);
                            }
                        }
        }
		/// <summary>
		/// Gets the pixel data representing a thick slice (a.k.a. slab) of the volume.
		/// </summary>
		private static byte[] GetSlabPixelData(IVolumeReference volumeReference, Matrix resliceAxes, Vector3D stackOrientation, int rows, int columns, int subsamples, float rowSpacing, float columnSpacing, float sliceThickness, VolumeInterpolationMode interpolation, VolumeProjectionMode projection)
		{
			if (subsamples <= 1) return GetSlicePixelData(volumeReference, resliceAxes, rows, columns, rowSpacing, columnSpacing, interpolation);
			var subsampleSpacing = sliceThickness/(subsamples - 1);

			using (var reslicer = new vtkImageReslice())
			using (var resliceAxesMatrix = new vtkMatrix4x4())
			using (var executive = reslicer.GetExecutive())
			using (var volume = volumeReference.Volume.CreateVtkVolumeHandle())
			{
				// update the reslice axes matrix with the values from the slicing orientation
				resliceAxesMatrix.SetElements(resliceAxes);

				// determine offset for start of slab (we centre the slab on the requested slice position, as DICOM defines "image position (patient)" to be centre of the thick slice)
				var slabOffset = volumeReference.RotateToVolumeOrientation(-sliceThickness/2f*stackOrientation) + new Vector3D(resliceAxes[0, 3], resliceAxes[1, 3], resliceAxes[2, 3]);
				resliceAxesMatrix.SetElement(0, 3, slabOffset.X);
				resliceAxesMatrix.SetElement(1, 3, slabOffset.Y);
				resliceAxesMatrix.SetElement(2, 3, slabOffset.Z);

				// register for errors on the reslicer
				reslicer.RegisterVtkErrorEvents();

				// set input to the volume
				reslicer.SetInput(volume.vtkImageData);
				reslicer.SetInformationInput(volume.vtkImageData);

				// instruct reslicer to output a 3D slab volume
				reslicer.SetOutputDimensionality(3);

				// use the volume's padding value for all pixels that are outside the volume
				reslicer.SetBackgroundLevel(volumeReference.PaddingValue);

				// ensure the slicer outputs at our desired spacing
				reslicer.SetOutputSpacing(columnSpacing, rowSpacing, subsampleSpacing);

				// set the reslice axes
				reslicer.SetResliceAxes(resliceAxesMatrix);

				// clamp the output based on the slice extent
				reslicer.SetOutputExtent(0, columns - 1, 0, rows - 1, 0, subsamples - 1);

				// set the output origin to the slice through-point (output image will be centered on this location)
				// VTK output origin is derived from the center image being 0,0
				reslicer.SetOutputOrigin(-columns*columnSpacing/2, -rows*rowSpacing/2, 0);

				// select the requested interpolation mode
				switch (interpolation)
				{
					case VolumeInterpolationMode.NearestNeighbor:
						reslicer.SetInterpolationModeToNearestNeighbor();
						break;
					case VolumeInterpolationMode.Linear:
						reslicer.SetInterpolationModeToLinear();
						break;
					case VolumeInterpolationMode.Cubic:
						reslicer.SetInterpolationModeToCubic();
						break;
				}

				// select the requested slab projection mode
				Action<IntPtr, byte[], int, int, int, bool> slabAggregator;
				switch (projection)
				{
					case VolumeProjectionMode.Maximum:
						slabAggregator = SlabProjection.AggregateSlabMaximumIntensity;
						break;
					case VolumeProjectionMode.Minimum:
						slabAggregator = SlabProjection.AggregateSlabMinimumIntensity;
						break;
					case VolumeProjectionMode.Average:
					default:
						slabAggregator = SlabProjection.AggregateSlabAverageIntensity;
						break;
				}

				// register for errors on the reslicer executive
				executive.RegisterVtkErrorEvents();
				executive.Update();

				// get the slice output
				using (var imageData = reslicer.GetOutput())
				{
					var pixelData = SlabVtkImageData(imageData, slabAggregator, volumeReference.BitsPerVoxel, volumeReference.Signed);
					imageData.ReleaseData();
					return pixelData;
				}
			}
		}