Exemple #1
0
        private vtkImageData CreateVtkVolume()
        {
            vtkImageData vtkVolume = new vtkImageData();

            VtkHelper.RegisterVtkErrorEvents(vtkVolume);

            vtkVolume.SetDimensions(ArrayDimensions.Width, ArrayDimensions.Height, ArrayDimensions.Depth);
            vtkVolume.SetOrigin(Origin.X, Origin.Y, Origin.Z);
            vtkVolume.SetSpacing(VoxelSpacing.X, VoxelSpacing.Y, VoxelSpacing.Z);

            if (!this.Signed)
            {
                vtkVolume.SetScalarTypeToUnsignedShort();
                vtkVolume.GetPointData().SetScalars(
                    VtkHelper.ConvertToVtkUnsignedShortArray(_volumeDataUInt16));
            }
            else
            {
                vtkVolume.SetScalarTypeToShort();
                vtkVolume.GetPointData().SetScalars(
                    VtkHelper.ConvertToVtkShortArray(_volumeDataInt16));
            }

            // This call is necessary to ensure vtkImageData data's info is correct (e.g. updates WholeExtent values)
            vtkVolume.UpdateInformation();

            return(vtkVolume);
        }
Exemple #2
0
        private static byte[] MipPixelDataFromVtkSlab(vtkImageData slabImageData)
        {
#if true // Do our own MIP, albeit slowly
            int[]  sliceDimensions = slabImageData.GetDimensions();
            int    sliceDataSize   = sliceDimensions[0] * sliceDimensions[1];
            IntPtr slabDataPtr     = slabImageData.GetScalarPointer();

            byte[] pixelData = MemoryManager.Allocate <byte>(sliceDataSize * sizeof(short));

            // Init with first slice
            Marshal.Copy(slabDataPtr, pixelData, 0, sliceDataSize * sizeof(short));

            // Walk through other slices, finding maximum
            unsafe
            {
                short *psSlab = (short *)slabDataPtr;

                fixed(byte *pbFrame = pixelData)
                {
                    short *psFrame = (short *)pbFrame;

                    for (int sliceIndex = 1; sliceIndex < sliceDimensions[2]; sliceIndex++)
                    {
                        for (int i = 0; i < sliceDataSize - 1; ++i)
                        {
                            int slabIndex = sliceIndex * sliceDataSize + i;
                            if (psSlab[slabIndex] > psFrame[i])
                            {
                                psFrame[i] = psSlab[slabIndex];
                            }
                        }
                    }
                }
            }

            return(pixelData);
#else // Ideally we'd use VTK to do the MIP (MinIP, Average...)
            vtkVolumeRayCastMIPFunction mip    = new vtkVolumeRayCastMIPFunction();
            vtkVolumeRayCastMapper      mapper = new vtkVolumeRayCastMapper();

            mapper.SetVolumeRayCastFunction(mip);
            mapper.SetInput(slabImageData);

            //TODO: Need to figure out how to use mapper to output vtkImageData

            vtkImageAlgorithm algo = new vtkImageAlgorithm();
            algo.SetInput(mapper.GetOutputDataObject(0));

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

                // Note: These report no output port, must have to do something else to get mapper to give us data
                //return exec.GetOutputData(0);
                return(mapper.GetOutputDataObject(0));
            }
#endif
        }
Exemple #3
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());
                }
            }
        }
Exemple #4
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);
                    }
                }
            }
        }
Exemple #5
0
 static Volume()
 {
     // Volume is the root of all VTK use through the API, so this is the place to initialize it
     VtkHelper.StaticInitializationHack();
 }