/// <summary> /// Gets a 2D slice from the 3D data. /// </summary> /// <param name="volume">Full 3D data.</param> /// <param name="sliceN">Number of slice to be selected.</param> /// <param name="axis">Axis on which selection will be made.</param> /// <returns></returns> public static vtkImageData volumeSlicer(vtkImageData volume, int[] sliceN, int axis) { //Initialize VOI extractor and permuter. //Permuter will correct the orientation of the output image vtkExtractVOI slicer = vtkExtractVOI.New(); vtkImagePermute permuter = vtkImagePermute.New(); //Connect data to slicer slicer.SetInput(volume); slicer.Update(); //Get data dimensions int[] dims = slicer.GetOutput().GetExtent(); //Get slice //Coronal plane if (axis == 0) { //Set VOI slicer.SetVOI(sliceN[0] - 1, sliceN[0], dims[2], dims[3], dims[4], dims[5]); slicer.Update(); //Permute image (not necessary here) permuter.SetInputConnection(slicer.GetOutputPort()); permuter.SetFilteredAxes(1, 2, 0); permuter.Update(); } //Transverse plane YZ if (axis == 1) { //Set VOI slicer.SetVOI(dims[0], dims[1], sliceN[1] - 1, sliceN[1], dims[4], dims[5]); slicer.Update(); //Permute image permuter.SetInputConnection(slicer.GetOutputPort()); permuter.SetFilteredAxes(0, 2, 1); permuter.Update(); } //Transverse plane, XZ if (axis == 2) { //Set VOI slicer.SetVOI(dims[0], dims[1], dims[2], dims[3], sliceN[2] - 1, sliceN[2]); slicer.Update(); //Permute image permuter.SetInputConnection(slicer.GetOutputPort()); permuter.SetFilteredAxes(0, 1, 2); permuter.Update(); } //slicer.Update(); //Return copy of the slice return(permuter.GetOutput()); }
/// <summary> /// Converts 3D byte array to vtkImageData. /// </summary> /// <param name="data">Input array.</param> /// <param name="orientation">Data orientation as a list of axes (0-2)</param> /// <returns>Converted array.</returns> public static vtkImageData byteToVTK(byte[,,] data, int[] orientation = null) { //Get input dimensions int[] dims = new int[] { data.GetLength(0), data.GetLength(1), data.GetLength(2) }; //Create VTK data for putput vtkImageData vtkdata = vtkImageData.New(); //Character array for conversion vtkUnsignedCharArray charArray = vtkUnsignedCharArray.New(); //Pin byte array GCHandle pinnedArray = GCHandle.Alloc(data, GCHandleType.Pinned); //Set character array input charArray.SetArray(pinnedArray.AddrOfPinnedObject(), dims[0] * dims[1] * dims[2], 1); //Set vtkdata properties and connect array //Data from char array vtkdata.GetPointData().SetScalars(charArray); //Number of scalars/pixel vtkdata.SetNumberOfScalarComponents(1); //Data extent, 1st and last axis are swapped from the char array //Data is converted back to original orientation vtkdata.SetExtent(0, dims[2] - 1, 0, dims[1] - 1, 0, dims[0] - 1); //Scalar type vtkdata.SetScalarTypeToUnsignedChar(); vtkdata.SetSpacing(1.0, 1.0, 1.0); vtkdata.Update(); pinnedArray.Free(); //Return vtk data if (orientation == null) { return(vtkdata); } else { vtkImagePermute permuter = vtkImagePermute.New(); permuter.SetInput(vtkdata); permuter.SetFilteredAxes(orientation[0], orientation[1], orientation[2]); permuter.Update(); return(permuter.GetOutput()); } }
/// <summary> /// Scans the input mask slice by slice and selects the largest binary component of each slice. /// Return cleaned mask as vtkImageData /// </summary> /// <param name="input"></param> /// <param name="extent"></param> /// <param name="threshold"></param> /// <param name="axes"></param> /// <returns></returns> public static vtkImageData FalsePositiveSuppresion(vtkImageData input, int[] extent, double threshold, int axis, double scale = 1.0) { //Slice extractor vtkExtractVOI slicer = vtkExtractVOI.New(); //Permuter vtkImagePermute permuter = vtkImagePermute.New(); //List of outputs List <byte[, , ]> outputs = new List <byte[, , ]>(); //List of output orientations List <int[]> orientations = new List <int[]>(); //vtkImageData size int[] full_extent = input.GetExtent(); //Set range for slices int start = 0, stop = 0; int[] size = new int[2]; int[] outextent = new int[4]; if (axis == 0) { start = extent[0]; stop = extent[1]; size = new int[] { extent[3] - extent[2] + 1, extent[5] - extent[4] + 1 }; outextent = new int[] { extent[2], extent[3] + 1, extent[4], extent[5] + 1 }; } if (axis == 1) { start = extent[2]; stop = extent[3]; size = new int[] { extent[1] - extent[0] + 1, extent[5] - extent[4] + 1 }; outextent = new int[] { extent[0], extent[1] + 1, extent[4], extent[5] + 1 }; } if (axis == 2) { start = extent[4]; stop = extent[5]; size = new int[] { extent[1] - extent[0] + 1, extent[3] - extent[2] + 1 }; outextent = new int[] { extent[0], extent[1] + 1, extent[2], extent[3] + 1 }; } //Temporary array for output byte[,,] output = new byte[full_extent[1] + 1, full_extent[3] + 1, full_extent[5] + 1]; int[] outsize = new int[] { size[0], size[1], stop - start + 1 }; //Loop over current axis for (int k = start; k < stop; k++) { byte[] bytedata = new byte[size[0] * size[1]]; //Select slice if (axis == 0) { slicer.Dispose(); slicer = vtkExtractVOI.New(); slicer.SetInput(input); slicer.SetVOI(k, k, extent[2], extent[3], extent[4], extent[5]); slicer.Update(); permuter.Dispose(); permuter = vtkImagePermute.New(); permuter.SetInput(slicer.GetOutput()); permuter.SetFilteredAxes(1, 2, 0); permuter.Update(); } if (axis == 1) { slicer.Dispose(); slicer = vtkExtractVOI.New(); slicer.SetInput(input); slicer.SetVOI(extent[0], extent[1], k, k, extent[4], extent[5]); slicer.Update(); permuter.Dispose(); permuter = vtkImagePermute.New(); permuter.SetInput(slicer.GetOutput()); permuter.SetFilteredAxes(0, 2, 1); permuter.Update(); } if (axis == 2) { slicer.Dispose(); slicer = vtkExtractVOI.New(); slicer.SetInput(input); slicer.SetVOI(extent[0], extent[1], extent[2], extent[3], k, k); slicer.Update(); permuter.Dispose(); permuter = vtkImagePermute.New(); permuter.SetInput(slicer.GetOutput()); permuter.SetFilteredAxes(0, 1, 2); permuter.Update(); } //Convert data to byte bytedata = DataTypes.vtkToByte(permuter.GetOutput()); slicer.Dispose(); permuter.Dispose(); //convert data to Mat Mat image = new Mat(size[1], size[0], MatType.CV_8UC1, bytedata); //Get largest binary object Mat bw = Processing.LargestBWObject(image, 0.7 * 255.0); //Set slice to byte array if (bw.Sum().Val0 > 0) { output = DataTypes.setByteSlice(output, bw, outextent, axis, k); } } return(DataTypes.byteToVTK(output)); }