/// <summary> /// Calculates mean and standard deviation images from volume-of-interest /// along third axis (z). /// </summary> /// <param name="input">Input volume as vtkImageData.</param> /// <param name="meanImage">Mean 2D image.</param> /// <param name="stdImage">Standard deviation 2D image.</param> public static void MeanAndStd(vtkImageData input, out double[,] meanImage, out double[,] stdImage) { //Get data extent int[] ext = input.GetExtent(); int[] dims = new int[] { ext[3] - ext[2] + 1, ext[1] - ext[0] + 1, ext[5] - ext[4] + 1 }; Console.WriteLine("Input shape: {0}, {1}, {2}".Format(dims[0], dims[1], dims[2])); // Convert to byte volume byte[] bytedata = DataTypes.vtkToByte(input); byte[,,] bytevolume = DataTypes.VectorToVolume(bytedata, dims); //int[] dims = new int[] { bytedata.GetLength(0), bytedata.GetLength(1), bytedata.GetLength(2) }; double[,] mean = new double[dims[0], dims[1]]; double[,] std = new double[dims[0], dims[1]]; Parallel.For(0, dims[0], i => { Parallel.For(0, dims[1], j => { //double[] temp = new double[dims[2]]; // has to be initialized in the loop double[] temp = new double[0]; // has to be initialized in the loop for (int k = 0; k < dims[2]; k++) { //temp[k] = bytevolume[i, j, k]; if (bytevolume[i, j, k] > 0) { temp.Concatenate(bytevolume[i, j, k]); } } if (temp.Length > 0) { mean[i, j] = temp.Average(); std[i, j] = Math.Sqrt(temp .Subtract(temp.Average()) .Pow(2) .Sum() / (temp.Length - 1)); } else { mean[i, j] = 0; std[i, j] = 0; } }); }); meanImage = mean; stdImage = std; }
/// <summary> /// Calculates size[0] x size[0] x size[1] cubic volume of surface from the center of the sample. /// Currently performs the calculation from upper third of the sample to save memory. /// Creates a copy from the full data array, then crops the copy to 1/3 size. /// </summary> /// <param name="volume">Input sample data that contains vtkImageData.</param> /// <param name="threshold">Grayscale threshold for sample surface and centering.</param> /// <param name="size">Size of the calculated surface volume.</param> /// <param name="surfacecoordinates">Array of z-coordinates of sample surface. These can be used with size parameter to visualize the surface volume.</param> /// <param name="surfacevoi">Calculated surface volume.</param> public static void SurfaceExtraction(ref Rendering.renderPipeLine volume, int threshold, int[] size, out int[,] surfacecoordinates, out byte[,,] surfacevoi) { // Convert vtkImageData to byte[,,] int[] dims = volume.getDims(); dims = new int[] { dims[1] + 1, dims[3] + 1, dims[5] + 1 }; byte[,,] byteVolume = DataTypes.VectorToVolume( DataTypes.vtkToByte(volume.idata), dims); // Crop to upper third of the sample int[] crop = { 0, byteVolume.GetLength(0) - 1, 0, byteVolume.GetLength(1) - 1, 0, (int)Math.Floor((double)byteVolume.GetLength(2) / 3) }; byteVolume = Functions.Crop3D(byteVolume, crop); // Get sample center coordinates int[] center = GetCenter(byteVolume, threshold); // Get surface GetSurface(byteVolume, center, size, threshold, out surfacecoordinates, out surfacevoi); // Free memory byteVolume = null; }
/// <summary> /// Calculates size[0] x size[0] x size[1] cubic volume of surface from the center of the sample. /// Currently performs the calculation from upper third of the sample to save memory. /// Creates a copy from the full data array, then crops the copy to 1/3 size. /// </summary> /// <param name="volume">Input sample data that contains vtkImageData.</param> /// <param name="threshold">Grayscale threshold for sample surface and centering.</param> /// <param name="size">Size of the calculated surface volume.</param> /// <param name="mode">Cartilage area selected fro VOI extraction. Possible ones: "surface", "deep", "calcified".</param> /// <param name="surfacecoordinates">Array of z-coordinates of sample surface. These can be used with size parameter to visualize the surface volume.</param> /// <param name="surfacevoi">Calculated surface volume.</param> public static void VOIExtraction(ref Rendering.renderPipeLine volume, int threshold, int[] size, string mode, out int[,] surfacecoordinates, out byte[,,] surfacevoi) { // Get cropping dimensions int[] crop = volume.idata.GetExtent(); crop[4] = (int)Math.Round(crop[5] / 2.0); // Crop and flip the volume var cropped = volume.getVOI(crop); var flipper = vtkImageFlip.New(); flipper.SetInput(cropped); flipper.SetFilteredAxes(2); flipper.Update(); // Render cropped volume //Rendering.RenderToNewWindow(flipper.GetOutput()); // Convert vtkImageData to byte[,,] int[] dims = new int[] { (crop[1] - crop[0]) + 1, (crop[3] - crop[2]) + 1, (crop[5] - crop[4]) + 1 }; byte[,,] byteVolume = DataTypes.VectorToVolume( DataTypes.vtkToByte(flipper.GetOutput()), dims); // Get sample center coordinates //int[] center = GetCenter(byteVolume, threshold); int[] center = new int[] { dims[0] / 2, dims[1] / 2 }; // Get surface GetSurface(byteVolume, center, size, threshold, out surfacecoordinates, out surfacevoi); // Free memory byteVolume = null; cropped = null; flipper = null; }