Ejemplo n.º 1
0
        private static void ResliceVolume(vtkImageData volume)
        {
            using (var reslicer = new vtkImageReslice())
            {
                RegisterVtkErrorEvents(reslicer);
                reslicer.SetInput(volume);
                reslicer.SetInformationInput(volume);

                // Must instruct reslicer to output 2D images
                reslicer.SetOutputDimensionality(2);

                // Use the volume's padding value for all pixels that are outside the volume
                reslicer.SetBackgroundLevel(0);

                // This ensures VTK obeys the real spacing, results in all VTK slices being isotropic.
                //	Effective spacing is the minimum of these three.
                reslicer.SetOutputSpacing(1.0, 1.0, 1.0);

                using (vtkMatrix4x4 resliceAxesMatrix = ConvertToVtkMatrix(new double[, ] {
                    { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 }
                }))
                {
                    reslicer.SetResliceAxes(resliceAxesMatrix);

                    // Clamp the output based on the slice extent
                    const int sliceExtentX = 50;
                    const int sliceExtentY = 50;
                    reslicer.SetOutputExtent(0, sliceExtentX - 1, 0, sliceExtentY - 1, 0, 0);

                    // Set the output origin to reflect the slice through point. The slice extent is
                    //	centered on the slice through point.
                    // VTK output origin is derived from the center image being 0,0
                    const float originX = -sliceExtentX * 1f / 2;
                    const float originY = -sliceExtentY * 1f / 2;
                    reslicer.SetOutputOrigin(originX, originY, 0);

                    reslicer.SetInterpolationModeToLinear();

                    using (vtkExecutive exec = reslicer.GetExecutive())
                    {
                        RegisterVtkErrorEvents(exec);
                        exec.Update();
                    }

                    using (var output = reslicer.GetOutput())
                    {
                        // just to give it something to do with the output
                        GC.KeepAlive(output);
                    }
                }
            }
        }
Ejemplo n.º 2
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);
                            }
                        }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Gets the pixel data representing a thin slice of the volume.
        /// </summary>
        private static byte[] GetSlicePixelData(IVolumeReference volumeReference, Matrix resliceAxes, int rows, int columns, float rowSpacing, float columnSpacing, VolumeInterpolationMode interpolation)
        {
            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);

                            // 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 2D images
                            reslicer.SetOutputDimensionality(2);

                            // 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, Math.Min(columnSpacing, rowSpacing));

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

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

                            // 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;
                            }

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

                            // get the slice output
                            using (var imageData = reslicer.GetOutput())
                            {
                                var pixelData = ReadVtkImageData(imageData);
                                imageData.ReleaseData();
                                return(pixelData);
                            }
                        }
        }
Ejemplo n.º 4
0
	// Extract slab in specified orientation, if slabThickness is 1, this is identical
	//	to GenerateVtkSlice above, so they should be collapsed at some point.
	// TODO: Tie into Dicom for slice, will need to adjust thickness at least
		private vtkImageData GenerateVtkSlab(Matrix resliceAxes, int slabThicknessInVoxels)
		{
            VtkHelper.StaticInitializationHack();

			// Thickness should be at least 1
			if (slabThicknessInVoxels < 1)
				slabThicknessInVoxels = 1;

			using (vtkImageReslice reslicer = new vtkImageReslice())
			{
				VtkHelper.RegisterVtkErrorEvents(reslicer);

				// Obtain a pinned VTK volume for the reslicer. We'll release this when
				//	VTK is done reslicing.
				vtkImageData volumeVtkWrapper = _volume.ObtainPinnedVtkVolume();
				reslicer.SetInput(volumeVtkWrapper);
				reslicer.SetInformationInput(volumeVtkWrapper);

				if (slabThicknessInVoxels > 1)
					reslicer.SetOutputDimensionality(3);
				else
					reslicer.SetOutputDimensionality(3);

				// Use the volume's padding value for all pixels that are outside the volume
				reslicer.SetBackgroundLevel(_volume.PadValue);

				// This ensures VTK obeys the real spacing, results in all VTK slices being isotropic.
				//	Effective spacing is the minimum of these three.
				reslicer.SetOutputSpacing(_volume.Spacing.X, _volume.Spacing.Y, _volume.Spacing.Z);

				reslicer.SetResliceAxes(VtkHelper.ConvertToVtkMatrix(resliceAxes));

				// Clamp the output based on the slice extent
				int sliceExtentX = GetSliceExtentX();
				int sliceExtentY = GetSliceExtentY();
				reslicer.SetOutputExtent(0, sliceExtentX - 1, 0, sliceExtentY - 1, 0, slabThicknessInVoxels-1);

				// Set the output origin to reflect the slice through point. The slice extent is
				//	centered on the slice through point.
				// VTK output origin is derived from the center image being 0,0
				float originX = -sliceExtentX * EffectiveSpacing / 2;
				float originY = -sliceExtentY * EffectiveSpacing / 2;
				reslicer.SetOutputOrigin(originX, originY, 0);

				switch (_slicing.InterpolationMode)
				{
					case InterpolationModes.NearestNeighbor:
						reslicer.SetInterpolationModeToNearestNeighbor();
						break;
					case InterpolationModes.Linear:
						reslicer.SetInterpolationModeToLinear();
						break;
					case InterpolationModes.Cubic:
						reslicer.SetInterpolationModeToCubic();
						break;
				}

				using (vtkExecutive exec = reslicer.GetExecutive())
				{
					VtkHelper.RegisterVtkErrorEvents(exec);

					exec.Update();

					_volume.ReleasePinnedVtkVolume();

					return reslicer.GetOutput();
				}
			}
		}
Ejemplo n.º 5
0
		// Extract slice in specified orientation
		private vtkImageData GenerateVtkSlice(Matrix resliceAxes)
		{
			using (vtkImageReslice reslicer = new vtkImageReslice())
			{
				VtkHelper.RegisterVtkErrorEvents(reslicer);

				// Obtain a pinned VTK volume for the reslicer. We'll release this when
				//	VTK is done reslicing.
				using (var volume = _volume.Volume.CreateVtkVolumeHandle())
				{
					reslicer.SetInput(volume.vtkImageData);
					reslicer.SetInformationInput(volume.vtkImageData);

					// Must instruct reslicer to output 2D images
					reslicer.SetOutputDimensionality(2);

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

					// This ensures VTK obeys the real spacing, results in all VTK slices being isotropic.
					//	Effective spacing is the minimum of these three.
					reslicer.SetOutputSpacing(_volume.Volume.VoxelSpacing.X, _volume.Volume.VoxelSpacing.Y, _volume.Volume.VoxelSpacing.Z);

					using (vtkMatrix4x4 resliceAxesMatrix = VtkHelper.ConvertToVtkMatrix(resliceAxes))
					{
						reslicer.SetResliceAxes(resliceAxesMatrix);

						// Clamp the output based on the slice extent
						int sliceExtentX = GetSliceExtentX();
						int sliceExtentY = GetSliceExtentY();
						reslicer.SetOutputExtent(0, sliceExtentX - 1, 0, sliceExtentY - 1, 0, 0);

						// Set the output origin to reflect the slice through point. The slice extent is
						//	centered on the slice through point.
						// VTK output origin is derived from the center image being 0,0
						float originX = -sliceExtentX*EffectiveSpacing/2;
						float originY = -sliceExtentY*EffectiveSpacing/2;
						reslicer.SetOutputOrigin(originX, originY, 0);

						switch (_slicerParams.InterpolationMode)
						{
							case VolumeSlicerInterpolationMode.NearestNeighbor:
								reslicer.SetInterpolationModeToNearestNeighbor();
								break;
							case VolumeSlicerInterpolationMode.Linear:
								reslicer.SetInterpolationModeToLinear();
								break;
							case VolumeSlicerInterpolationMode.Cubic:
								reslicer.SetInterpolationModeToCubic();
								break;
						}

						using (vtkExecutive exec = reslicer.GetExecutive())
						{
							VtkHelper.RegisterVtkErrorEvents(exec);
							exec.Update();
						}

						var output = reslicer.GetOutput();
						//Just in case VTK uses the matrix internally.
						return output;
					}
				}
			}
		}
Ejemplo n.º 6
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 <= 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;
				}
			}
		}
Ejemplo n.º 7
0
		/// <summary>
		/// Gets the pixel data representing a thin slice of the volume.
		/// </summary>
		private static byte[] GetSlicePixelData(IVolumeReference volumeReference, Matrix resliceAxes, int rows, int columns, float rowSpacing, float columnSpacing, VolumeInterpolationMode interpolation)
		{
			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);

				// 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 2D images
				reslicer.SetOutputDimensionality(2);

				// 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, Math.Min(columnSpacing, rowSpacing));

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

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

				// 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;
				}

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

				// get the slice output
				using (var imageData = reslicer.GetOutput())
				{
					var pixelData = ReadVtkImageData(imageData);
					imageData.ReleaseData();
					return pixelData;
				}
			}
		}
Ejemplo n.º 8
0
		private static void ResliceVolume(vtkImageData volume)
		{
            using (var reslicer = new vtkImageReslice())
			{
				RegisterVtkErrorEvents(reslicer);
				reslicer.SetInput(volume);
				reslicer.SetInformationInput(volume);

				// Must instruct reslicer to output 2D images
				reslicer.SetOutputDimensionality(2);

				// Use the volume's padding value for all pixels that are outside the volume
				reslicer.SetBackgroundLevel(0);

				// This ensures VTK obeys the real spacing, results in all VTK slices being isotropic.
				//	Effective spacing is the minimum of these three.
				reslicer.SetOutputSpacing(1.0, 1.0, 1.0);

                using (vtkMatrix4x4 resliceAxesMatrix = ConvertToVtkMatrix(new double[,] {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}))
				{
					reslicer.SetResliceAxes(resliceAxesMatrix);

					// Clamp the output based on the slice extent
					const int sliceExtentX = 50;
					const int sliceExtentY = 50;
					reslicer.SetOutputExtent(0, sliceExtentX - 1, 0, sliceExtentY - 1, 0, 0);

					// Set the output origin to reflect the slice through point. The slice extent is
					//	centered on the slice through point.
					// VTK output origin is derived from the center image being 0,0
					const float originX = -sliceExtentX*1f/2;
					const float originY = -sliceExtentY*1f/2;
					reslicer.SetOutputOrigin(originX, originY, 0);

					reslicer.SetInterpolationModeToLinear();

					using (vtkExecutive exec = reslicer.GetExecutive())
					{
						RegisterVtkErrorEvents(exec);
						exec.Update();
					}

					using (var output = reslicer.GetOutput())
					{
						// just to give it something to do with the output
                        GC.KeepAlive(output);
					}
				}
			}
		}
Ejemplo n.º 9
0
        // Extract slab in specified orientation, if slabThickness is 1, this is identical
        //	to GenerateVtkSlice above, so they should be collapsed at some point.
        // TODO: Tie into Dicom for slice, will need to adjust thickness at least
        private vtkImageData GenerateVtkSlab(Matrix resliceAxes, int slabThicknessInVoxels)
        {
            VtkHelper.StaticInitializationHack();

            // Thickness should be at least 1
            if (slabThicknessInVoxels < 1)
            {
                slabThicknessInVoxels = 1;
            }

            using (vtkImageReslice reslicer = new vtkImageReslice())
            {
                VtkHelper.RegisterVtkErrorEvents(reslicer);

                // Obtain a pinned VTK volume for the reslicer. We'll release this when
                //	VTK is done reslicing.
                vtkImageData volumeVtkWrapper = _volume.ObtainPinnedVtkVolume();
                reslicer.SetInput(volumeVtkWrapper);
                reslicer.SetInformationInput(volumeVtkWrapper);

                if (slabThicknessInVoxels > 1)
                {
                    reslicer.SetOutputDimensionality(3);
                }
                else
                {
                    reslicer.SetOutputDimensionality(3);
                }

                // Use the volume's padding value for all pixels that are outside the volume
                reslicer.SetBackgroundLevel(_volume.PadValue);

                // This ensures VTK obeys the real spacing, results in all VTK slices being isotropic.
                //	Effective spacing is the minimum of these three.
                reslicer.SetOutputSpacing(_volume.Spacing.X, _volume.Spacing.Y, _volume.Spacing.Z);

                reslicer.SetResliceAxes(VtkHelper.ConvertToVtkMatrix(resliceAxes));

                // Clamp the output based on the slice extent
                int sliceExtentX = GetSliceExtentX();
                int sliceExtentY = GetSliceExtentY();
                reslicer.SetOutputExtent(0, sliceExtentX - 1, 0, sliceExtentY - 1, 0, slabThicknessInVoxels - 1);

                // Set the output origin to reflect the slice through point. The slice extent is
                //	centered on the slice through point.
                // VTK output origin is derived from the center image being 0,0
                float originX = -sliceExtentX * EffectiveSpacing / 2;
                float originY = -sliceExtentY * EffectiveSpacing / 2;
                reslicer.SetOutputOrigin(originX, originY, 0);

                switch (_slicing.InterpolationMode)
                {
                case InterpolationModes.NearestNeighbor:
                    reslicer.SetInterpolationModeToNearestNeighbor();
                    break;

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

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

                using (vtkExecutive exec = reslicer.GetExecutive())
                {
                    VtkHelper.RegisterVtkErrorEvents(exec);

                    exec.Update();

                    _volume.ReleasePinnedVtkVolume();

                    return(reslicer.GetOutput());
                }
            }
        }
Ejemplo n.º 10
0
        // Extract slice in specified orientation
        private vtkImageData GenerateVtkSlice(Matrix resliceAxes)
        {
            using (vtkImageReslice reslicer = new vtkImageReslice())
            {
                VtkHelper.RegisterVtkErrorEvents(reslicer);

                // Obtain a pinned VTK volume for the reslicer. We'll release this when
                //	VTK is done reslicing.
                using (var volume = _volume.Volume.CreateVtkVolumeHandle())
                {
                    reslicer.SetInput(volume.vtkImageData);
                    reslicer.SetInformationInput(volume.vtkImageData);

                    // Must instruct reslicer to output 2D images
                    reslicer.SetOutputDimensionality(2);

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

                    // This ensures VTK obeys the real spacing, results in all VTK slices being isotropic.
                    //	Effective spacing is the minimum of these three.
                    reslicer.SetOutputSpacing(_volume.Volume.VoxelSpacing.X, _volume.Volume.VoxelSpacing.Y, _volume.Volume.VoxelSpacing.Z);

                    using (vtkMatrix4x4 resliceAxesMatrix = VtkHelper.ConvertToVtkMatrix(resliceAxes))
                    {
                        reslicer.SetResliceAxes(resliceAxesMatrix);

                        // Clamp the output based on the slice extent
                        int sliceExtentX = GetSliceExtentX();
                        int sliceExtentY = GetSliceExtentY();
                        reslicer.SetOutputExtent(0, sliceExtentX - 1, 0, sliceExtentY - 1, 0, 0);

                        // Set the output origin to reflect the slice through point. The slice extent is
                        //	centered on the slice through point.
                        // VTK output origin is derived from the center image being 0,0
                        float originX = -sliceExtentX * EffectiveSpacing / 2;
                        float originY = -sliceExtentY * EffectiveSpacing / 2;
                        reslicer.SetOutputOrigin(originX, originY, 0);

                        switch (_slicerParams.InterpolationMode)
                        {
                        case VolumeSlicerInterpolationMode.NearestNeighbor:
                            reslicer.SetInterpolationModeToNearestNeighbor();
                            break;

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

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

                        using (vtkExecutive exec = reslicer.GetExecutive())
                        {
                            VtkHelper.RegisterVtkErrorEvents(exec);
                            exec.Update();
                        }

                        var output = reslicer.GetOutput();
                        //Just in case VTK uses the matrix internally.
                        return(output);
                    }
                }
            }
        }
        //切片模式_绘制
        private void DrawMode_Slice()
        {
            int[]    xyz = m_ImageData.GetDimensions();
            double[] sp  = m_ImageData.GetSpacing();

            double[] pos = new double[] { m_XPos, m_YPos, m_ZPos };

            #region -------------------XOY切片(垂直Z轴)-------------------

            m_ImageResliceXOY = vtkImageReslice.New();
            m_ImageResliceXOY.SetInput(m_ImageData);
            m_ImageResliceXOY.SetResliceAxesDirectionCosines(
                1, 0, 0,
                0, 1, 0,
                0, 0, 1
                );
            m_ImageResliceXOY.InterpolateOn();
            m_ImageResliceXOY.SetInterpolationModeToNearestNeighbor();
            m_ImageResliceXOY.SetResliceAxesOrigin(pos[0], pos[1], pos[2]);
            m_ImageResliceXOY.SetOutputDimensionality(2);
            m_ImageResliceXOY.Update();

            m_TextureXOY = vtkTexture.New();
            m_TextureXOY.InterpolateOff();
            m_TextureXOY.SetInput(m_ImageResliceXOY.GetOutput());
            m_TextureXOY.SetLookupTable(m_LookupTable);
            m_TextureXOY.MapColorScalarsThroughLookupTableOn();

            //---------------------set plane position----------
            m_PlaneSourceXOY = vtkPlaneSource.New();
            m_PlaneSourceXOY.SetXResolution(xyz[0]);
            m_PlaneSourceXOY.SetYResolution(xyz[1]);
            m_PlaneSourceXOY.SetOrigin(0, 0, 0);
            m_PlaneSourceXOY.SetPoint1((xyz[0] - 1) * sp[0], 0, 0);
            m_PlaneSourceXOY.SetPoint2(0, (xyz[1] - 1) * sp[1], 0);
            m_PlaneSourceXOY.Push(pos[2]);

            //---------------------pipeline--------------------
            m_PlaneMapperXOY = vtkPolyDataMapper.New();
            m_PlaneMapperXOY.SetInput(m_PlaneSourceXOY.GetOutput());

            m_ActorXOY = vtkActor.New();
            m_ActorXOY.SetMapper(m_PlaneMapperXOY);
            m_ActorXOY.SetTexture(m_TextureXOY);

            #endregion

            #region -------------------XOZ切片(垂直Y轴)-------------------

            m_ImageResliceXOZ = vtkImageReslice.New();
            m_ImageResliceXOZ.SetInput(m_ImageData);
            m_ImageResliceXOZ.SetResliceAxesDirectionCosines(
                1, 0, 0,
                0, 0, -1,
                0, 1, 0
                );
            m_ImageResliceXOZ.InterpolateOn();
            m_ImageResliceXOZ.SetInterpolationModeToNearestNeighbor();
            m_ImageResliceXOZ.SetResliceAxesOrigin(pos[0], pos[1], pos[2]);
            m_ImageResliceXOZ.SetOutputDimensionality(2);
            m_ImageResliceXOZ.Update();

            m_TextureXOZ = vtkTexture.New();
            m_TextureXOZ.SetInput(m_ImageResliceXOZ.GetOutput());
            m_TextureXOZ.SetLookupTable(m_LookupTable);
            m_TextureXOZ.MapColorScalarsThroughLookupTableOn();

            //---------------------set plane position--------------------
            m_PlaneSourceXOZ = vtkPlaneSource.New();
            m_PlaneSourceXOZ.SetXResolution(xyz[0]);
            m_PlaneSourceXOZ.SetYResolution(xyz[2]);
            m_PlaneSourceXOZ.SetOrigin(0, 0, (xyz[2] - 1) * sp[2]);
            m_PlaneSourceXOZ.SetPoint1((xyz[0] - 1) * sp[0], 0, (xyz[2] - 1) * sp[2]);
            m_PlaneSourceXOZ.SetPoint2(0, 0, 0);
            m_PlaneSourceXOZ.Push(pos[1]);

            //---------------------pipeline------------------------------
            m_PlaneMapperXOZ = vtkPolyDataMapper.New();
            m_PlaneMapperXOZ.SetInput(m_PlaneSourceXOZ.GetOutput());

            m_ActorXOZ = vtkActor.New();
            m_ActorXOZ.SetMapper(m_PlaneMapperXOZ);
            m_ActorXOZ.SetTexture(m_TextureXOZ);

            #endregion

            #region -------------------YOZ切片(垂直X轴)-------------------

            m_ImageResliceYOZ = vtkImageReslice.New();
            m_ImageResliceYOZ.SetInput(m_ImageData);
            m_ImageResliceYOZ.SetResliceAxesDirectionCosines(
                0, 0, -1,
                0, 1, 0,
                1, 0, 0
                );
            m_ImageResliceYOZ.InterpolateOn();
            m_ImageResliceYOZ.SetInterpolationModeToNearestNeighbor();
            m_ImageResliceYOZ.SetResliceAxesOrigin(pos[0], pos[1], pos[2]);
            m_ImageResliceYOZ.SetOutputDimensionality(2);
            m_ImageResliceYOZ.Update();

            m_TextureYOZ = vtkTexture.New();
            m_TextureYOZ.SetInput(m_ImageResliceYOZ.GetOutput());
            m_TextureYOZ.SetLookupTable(m_LookupTable);
            m_TextureYOZ.MapColorScalarsThroughLookupTableOn();

            //---------------------set plane position--------------------
            m_PlaneSourceYOZ = vtkPlaneSource.New();
            m_PlaneSourceYOZ.SetXResolution(xyz[2]);
            m_PlaneSourceYOZ.SetYResolution(xyz[1]);
            m_PlaneSourceYOZ.SetOrigin(0, 0, (xyz[2] - 1) * sp[2]);
            m_PlaneSourceYOZ.SetPoint1(0, 0, 0);
            m_PlaneSourceYOZ.SetPoint2(0, (xyz[1] - 1) * sp[1], (xyz[2] - 1) * sp[2]);
            m_PlaneSourceYOZ.Push(pos[0]);

            //---------------------pipeline------------------------------
            m_PlaneMapperYOZ = vtkPolyDataMapper.New();
            m_PlaneMapperYOZ.SetInput(m_PlaneSourceYOZ.GetOutput());

            m_ActorYOZ = vtkActor.New();
            m_ActorYOZ.SetMapper(m_PlaneMapperYOZ);
            m_ActorYOZ.SetTexture(m_TextureYOZ);

            #endregion

            m_Renderer.AddActor(m_ActorXOY);
            m_Renderer.AddActor(m_ActorXOZ);
            m_Renderer.AddActor(m_ActorYOZ);
        }