private void RotateImage(RotationOperation operation)
        {
            vtkImageReslice reslice   = vtkImageReslice.New();
            vtkTransform    transform = vtkTransform.New();

            transform.PostMultiply();

            double[] center = { 75, 100, 0 };
            transform.Translate(-center[0], -center[1], -center[2]);
            if (operation == RotationOperation.Forward)
            {
                transform.RotateZ(90);
            }
            else if (operation == RotationOperation.Back)
            {
                transform.RotateZ(-90);
            }
            transform.Translate(+center[0], +center[1], +center[2]);

            transform.Update();
            reslice.SetInput(_viewer.GetInput());
            reslice.SetResliceTransform(transform);
            reslice.Update();

            _viewer.SetInput(reslice.GetOutput());

            UpdateViewer();
        }
        /// <summary>
        /// Update the 2D visualization when the plane moved.
        /// </summary>
        /// <param name="plane">PlaneWidget which changed the coordinates.</param>
        public void PlaneMoved(vtkImagePlaneWidget plane)
        {
            vtkImageReslice reslice   = vtkImageReslice.New();
            vtkTransform    transform = vtkTransform.New();

            transform.PostMultiply();

            //TODO wyznaczenie centrum okna
            double[] center = { 75, 100, 0 };
            transform.Translate(-center[0], -center[1], -center[2]);
            transform.RotateZ(_orientation);
            transform.Translate(+center[0], +center[1], +center[2]);

            transform.Update();
            reslice.SetInput(plane.GetResliceOutput());
            reslice.SetResliceTransform(transform);
            reslice.Update();
            //
            vtkImageData viewerInputData;

            viewerInputData = reslice.GetOutput();

            _lastData = viewerInputData;

            _viewer.SetInput(viewerInputData);
            //
            //_viewer.SetInput(reslice.GetOutput());
            UpdateViewer();
        }
예제 #3
0
        /// <summary>
        /// Rotates volume along given axis.
        /// </summary>
        /// <param name="volume"></param>
        /// <param name="angles"></param>
        public static void RotateData(ref vtkImageData volume, double[] angles)
        {
            // Rotation along image center
            double[] center = volume.GetExtent().Divide(2);
            // Dimensions of rotated image
            int[] outExtent = volume.GetExtent().Multiply(1.1).Round().ToInt32();

            // Rotation parameters
            var rotate = new vtkTransform();

            rotate.Translate(center[1], center[3], center[5]);
            rotate.RotateX(angles[0]);
            rotate.RotateY(angles[1]);
            rotate.RotateZ(angles[2]); // z angle should be 0
            rotate.Translate(-center[1], -center[3], -center[5]);

            // Perform rotation
            var slice = new vtkImageReslice();

            slice.SetInput(volume);
            slice.SetResliceTransform(rotate);
            slice.SetInterpolationModeToCubic();
            slice.SetOutputSpacing(volume.GetSpacing()[0], volume.GetSpacing()[1], volume.GetSpacing()[2]);
            slice.SetOutputOrigin(volume.GetOrigin()[0], volume.GetOrigin()[1], volume.GetOrigin()[2]);
            slice.SetOutputExtent(outExtent[0], outExtent[1], outExtent[2], outExtent[3], outExtent[4], outExtent[5]);
        }
예제 #4
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);
                    }
                }
            }
        }
        //TODO

        public void DrawingModeRepaint()
        {
            if (_lastData == null)
            {
                return;
            }

            vtkImageReslice reslice   = vtkImageReslice.New();
            vtkTransform    transform = vtkTransform.New();

            transform.PostMultiply();

            //TODO wyznaczenie centrum okna
            double[] center = { 75, 100, 0 };
            transform.Translate(-center[0], -center[1], -center[2]);
            transform.RotateZ(_orientation);
            transform.Translate(+center[0], +center[1], +center[2]);

            transform.Update();

            reslice.SetInput(_lastData);
            reslice.SetResliceTransform(transform);
            reslice.Update();

            vtkImageData viewerInputData;

            if (!DrawingEnabled)
            {
                viewerInputData = reslice.GetOutput();
            }
            else
            {
                var resliceOutput = reslice.GetOutput();
                var sizeArray     = resliceOutput.GetDimensions();

                vtkImageCanvasSource2D imageCanvas = vtkImageCanvasSource2D.New();
                imageCanvas.SetScalarTypeToUnsignedChar();
                imageCanvas.SetExtent(0, sizeArray[0], 0, sizeArray[1], 0, 0);
                imageCanvas.DrawImage(0, 0, resliceOutput);

                DrawingUtils.Draw(imageCanvas, DrawingInfo);

                imageCanvas.Update();
                viewerInputData = imageCanvas.GetOutput();
            }
            _viewer.SetInput(viewerInputData);

            UpdateViewer();
        }
예제 #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 == 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);
                            }
                        }
        }
예제 #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);
                            }
                        }
        }
예제 #8
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();
				}
			}
		}
예제 #9
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;
					}
				}
			}
		}
예제 #10
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;
				}
			}
		}
예제 #11
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;
				}
			}
		}
예제 #12
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);
					}
				}
			}
		}
예제 #13
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());
                }
            }
        }
예제 #14
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);
        }
예제 #16
0
        /// <summary>
        /// Rotates 3D vtk volume around x and y axes.
        /// </summary>
        /// <param name="input"></param>
        /// <param name="angle"></param>
        /// <param name="axis"></param>
        /// <param name="out_extent"></param>
        /// <returns></returns>
        public static vtkImageData rotate_sample(vtkImageData input, double angle, int axis, int out_extent = 0)
        {
            //get input data dimensions
            int[] dims = input.GetExtent();
            //Compute centers
            int[] centers = new int[] { (dims[1] + dims[0]) / 2, (dims[3] + dims[2]) / 2, (dims[5] + dims[4]) / 2 };

            //Set rotation axis
            int[] axes = new int[3];
            axes[axis] = 1;

            int[] new_dims    = new int[] { dims[0], dims[1], dims[2], dims[3], dims[4], dims[5] };
            int[] new_centers = new int[] { centers[0], centers[1], centers[2] };

            //Compute new sample dimensions
            if (axis == 0)
            {
                new_dims[3] = (int)(Math.Cos(Math.Abs(angle / 180) * Math.PI) * new_dims[3] + Math.Sin(Math.Abs(angle / 180) * Math.PI) * new_dims[5]);
                new_dims[5] = (int)(Math.Sin(Math.Abs(angle / 180) * Math.PI) * new_dims[3] + Math.Cos(Math.Abs(angle / 180) * Math.PI) * new_dims[5]);

                new_centers[1] = (Math.Abs(new_dims[3]) + Math.Abs(new_dims[2])) / 2;
                new_centers[2] = (Math.Abs(new_dims[5]) + Math.Abs(new_dims[4])) / 2;
            }
            if (axis == 1)
            {
                new_dims[1] = (int)(Math.Cos(Math.Abs(angle / 180) * Math.PI) * new_dims[1] + Math.Sin(Math.Abs(angle / 180) * Math.PI) * new_dims[5]);
                new_dims[5] = (int)(Math.Sin(Math.Abs(angle / 180) * Math.PI) * new_dims[1] + Math.Cos(Math.Abs(angle / 180) * Math.PI) * new_dims[5]);

                new_centers[0] = (Math.Abs(new_dims[0]) + Math.Abs(new_dims[1])) / 2;
                new_centers[2] = (Math.Abs(new_dims[5]) + Math.Abs(new_dims[4])) / 2;
            }


            //Image transformation
            vtkTransform transform = vtkTransform.New();

            transform.Translate(centers[0], centers[1], centers[2]);
            transform.RotateWXYZ(angle, axes[0], axes[1], axes[2]);
            if (out_extent == 0)
            {
                transform.Translate(-centers[0], -centers[1], -centers[2]);
            }
            else
            {
                transform.Translate(-new_centers[0], -new_centers[1], -new_centers[2]);
            }

            //Console.ReadKey();

            transform.Update();

            //Compute new data extent
            int[] diff = new int[] { new_dims[1] - dims[1], new_dims[3] - dims[3], new_dims[5] - dims[5] };
            new_dims[0] += diff[0] / 2; new_dims[1] -= diff[0] / 2;
            new_dims[2] += diff[1] / 2; new_dims[3] -= diff[1] / 2;
            new_dims[4] += diff[2] / 2; new_dims[5] -= diff[2] / 2;



            //Image reslicing
            vtkImageReslice rotater = vtkImageReslice.New();

            rotater.SetInput(input);
            rotater.SetInformationInput(input);
            rotater.SetResliceTransform(transform);
            rotater.SetInterpolationModeToCubic();
            //rotater.SetInterpolationModeToLinear();
            if (out_extent == 1)
            {
                rotater.SetOutputSpacing(input.GetSpacing()[0], input.GetSpacing()[1], input.GetSpacing()[2]);
                rotater.SetOutputOrigin(input.GetOrigin()[0], input.GetOrigin()[1], input.GetOrigin()[2]);
                rotater.SetOutputExtent(new_dims[0], new_dims[1], new_dims[2], new_dims[3], new_dims[4], new_dims[5]);
            }
            rotater.Update();

            vtkImageData output = vtkImageData.New();

            output.DeepCopy(rotater.GetOutput());

            rotater.Dispose();
            transform.Dispose();

            return(output);
        }