public static IList <IList <float> > segment_sample(Rendering.renderPipeLine vtkObject, UNet model, int[] extent, int axis, int step = 1, float mu = 0, float sd = 0) { //Segmentation range int[] bounds = new int[] { extent[axis * 2], extent[axis * 2 + 1] }; //Output list IList <IList <float> > output = null; //Iterate over vtk data for (int k = 0; k < (bounds[1] - bounds[0]) / step; k++) { //Set current VOI and orientation int[] _curext = new int[6]; int[] _ori = new int[3]; if (axis == 0) { int start = extent[0] + k * step; int stop = Math.Min(extent[0] + (k + 1) * step - 1, extent[1]); _curext = new int[] { start, stop, extent[2], extent[3], extent[4], extent[5] }; _ori = new int[] { 2, 1, 0 }; } if (axis == 1) { int start = extent[2] + k * step; int stop = Math.Min(extent[2] + (k + 1) * step - 1, extent[3]); _curext = new int[] { extent[0], extent[1], start, stop, extent[4], extent[5] }; _ori = new int[] { 2, 0, 1 }; } if (axis == 2) { int start = extent[4] + k * step; int stop = Math.Min(extent[4] + (k + 1) * step - 1, extent[5]); _curext = new int[] { extent[0], extent[1], extent[2], extent[3], start, stop }; _ori = new int[] { 0, 1, 2 }; } //Extract VOI to float array float[] input_array = DataTypes.byteToFloat(DataTypes.vtkToByte(vtkObject.getVOI(_curext, _ori)), mu, sd); //Segment current slice IList <IList <float> > _cur = model.Inference(input_array); //Append results to output list if (output == null) { output = _cur; } else { //Loop over slices foreach (IList <float> item in _cur) { output.Add(item); } } GC.Collect(); } //Return output list return(output); }
public static void segmentation_pipeline(out List <vtkImageData> outputs, Rendering.renderPipeLine volume, int[] batch_d, int[] extent, int[] axes, string wpath, int bs = 2) { //Outputs outputs = new List <vtkImageData>(); //Get input dimensions int[] dims = volume.getDims(); // Initialize UNet UNet model = new UNet(); try { model.Initialize(24, batch_d, wpath, false); } catch (FileNotFoundException) { Console.WriteLine("Model not found"); return; } for (int k = 0; k < axes.Length; k++) { outputs.Add(vtkImageData.New()); } //Segment BCI from axis for (int k = 0; k < axes.Length; k++) { //Inference IList <IList <float> > result = segment_sample(volume, model, extent, axes[k], bs, (float)108.58790588378906, (float)47.622276306152344); //Copy result to vtkImagedata vtkImageData _tmp = IO.inference_to_vtk(result, new int[] { dims[1] + 1, dims[3] + 1, dims[5] + 1 }, extent, axes[k]); outputs.ElementAt(k).DeepCopy(_tmp); _tmp.Dispose(); result = null; } model.Dispose(); }
/// <summary> /// Calculates OA grade prediction. /// </summary> /// <param name="mod">Loaded model.</param> /// <param name="features">LBP features.</param> /// <param name="volume">Data array.</param> /// <returns>Returns string containing the OA grade</returns> public static string Predict(Model mod, ref int[,] features, ref Rendering.renderPipeLine volume) { // Default variables int threshold = 50; int[] size = { 400, 30 }; //int threshold = 5; //int[] size = { 10, 3 }; // Load default model string state = LoadModel(ref mod); // Surface extraction Processing.SurfaceExtraction(ref volume, threshold, size, out int[,] surfacecoordinates, out byte[,,] surface); // Mean and std images Processing.MeanAndStd(surface, out double[,] meanImage, out double[,] stdImage); // // LBP features // LBPLibrary.Functions.Save(@"C:\Users\sarytky\Desktop\trials\mean.png", meanImage, true); LBPLibrary.Functions.Save(@"C:\Users\sarytky\Desktop\trials\std.png", stdImage, true); features = LBP(meanImage.Add(stdImage)); // PCA double[,] dataAdjust = Processing.SubtractMean(features.ToDouble()); double[,] PCA = dataAdjust.Dot(mod.eigenVectors.ToDouble()); // Regression double[] grade = PCA.Dot(mod.weights).Add(1.5); //double sum = CompareGrades(grade); return("OA grade: " + grade[0].ToString("####.##", CultureInfo.InvariantCulture)); //return "Sum of differences between pretrained model and actual grade: " + sum.ToString("###.###", CultureInfo.InvariantCulture); }
public static void segmentation_pipeline(out List <vtkImageData> outputs, Rendering.renderPipeLine volume, int[] batch_d, int[] extent, int[] axes, int bs = 2) { //Outputs outputs = new List <vtkImageData>(); //Get input dimensions int[] dims = volume.getDims(); //Initialize unet string wpath = "Z:\\Tuomas\\UNetE3BN.h5"; UNet model = new UNet(); model.Initialize(24, batch_d, wpath, false); //Segment BCI from axis foreach (int axis in axes) { IList <IList <float> > result = segment_sample(volume, model, extent, axis, bs, (float)113.05652141, (float)39.87462853); //Convert back to vtkimage data vtkImageData tmp = IO.inference_to_vtk(result, new int[] { dims[1] + 1, dims[3] + 1, dims[5] + 1 }, extent, axis); outputs.Add(tmp); } }
/// <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; }
//Buttons //Load CT data private void fileButton_Click(object sender, EventArgs e) { label4.Text = "Loading: "; mainProgress.Value = 10; //Select a file and render volume if (fileDialog.ShowDialog() == DialogResult.OK) { if (is_rendering == 1) { //Remove renderer renWin.RemoveRenderer(renWin.GetRenderers().GetFirstRenderer()); volume.Dispose(); volume = null; GC.Collect(); } //Initialize new volume volume = new Rendering.renderPipeLine(); //Update renderwindow renderWindowControl_Load(this, null); fname = ""; //Get path and files string impath = fileDialog.FileName; string folpath = Path.GetDirectoryName(@impath); // Get sample name var file = Path.GetFileName(impath).Split('_'); for (int k = 0; k < file.Length - 1; k++) { fname += file[k]; if (k < file.Length - 2) { fname += "_"; } } mainProgress.Value = 50; //Load data volume.connectData(impath); mainProgress.Value = 70; //Get dimensions and set slices. Middle slice is set to current slice dims = volume.getDims(); sliceN[0] = (dims[1] + dims[0]) / 2; sliceN[1] = (dims[3] + dims[2]) / 2; sliceN[2] = (dims[5] + dims[4]) / 2; Console.WriteLine("Loaded fine"); //Connect slice to renderer volume.connectWindow(renWin); Console.WriteLine("Connected window fine"); //Render bool large = volume.renderVolume(); if (large) { Console.WriteLine("Too large sample. Memory limit is 2GB."); return; } Console.WriteLine("rendering.."); //Flags for GUI components is_rendering = 1; is_mask = 0; is_coronal = 0; is_sagittal = 0; //Saving flags save_mask = 0; save_vois = 0; //Orientation ori = -1; //Update pipeline parameters volume.updateCurrent(sliceN, ori, gray); volume.setVolumeColor(); //Update GUI maskButton.Text = "Load Mask"; maskLabel.Text = "No Mask Loaded"; coronalButton.Text = "Coronal, XZ"; sagittalButton.Text = "Sagittal, YZ"; TellSlice(); // Enable buttons sagittalButton.Enabled = true; coronalButton.Enabled = true; transverseButton.Enabled = true; volumeButton.Enabled = true; resetButton.Enabled = true; gminBar.Enabled = true; gmaxBar.Enabled = true; maskButton.Enabled = true; panel2.Enabled = true; sliceBar.Enabled = true; if (!large) { renderWindowControl.Enabled = true; } cropButton.Enabled = true; rotate_button.Enabled = true; getVoiButton.Enabled = false; segmentButton.Enabled = false; predict.Enabled = false; saveButton.Enabled = false; GC.Collect(); //Update GUI text to tell path to data folder fileLabel.Text = fname; tip = "Sample loaded and tools enabled"; gradeLabel.Text = tip; mainProgress.Value = 100; label4.Text = "Done"; } }
static void Main(string[] args) { //Path to data string path = "Z:\\3DHistoData\\rekisteroidyt\\32_L6MT_2_PTA_48h_Rec\\32_L6MT_2_PTA_48h_Rec\\Registration\\32_L6MT_2_PTA_48h__rec_Tar00000038.png"; string modelpath = "Z:\\Tuomas\\UNetE3bn.h5"; Mat im = new Mat(path, ImreadModes.GrayScale); Mat BW = im.Threshold(80.0, 255.0, ThresholdTypes.Binary); Mat E = BW.Sobel(MatType.CV_8UC1, 1, 1); Mat[] conts; HierarchyIndex[] H; E.FindContours(out conts, H, RetrievalModes.List, ContourApproximationModes.ApproxTC89KCOS); InputArray.Create(conts); Rect bbox = Cv2.BoundingRect(conts); int xmin = bbox.Left; int xmax = bbox.Right; int ymin = bbox.Bottom; int ymax = bbox.Top; Console.WriteLine("{0},{1}", xmin, ymin); Console.WriteLine("{0},{1}", xmin, ymax); Console.WriteLine("{0},{1}", xmax, ymin); Console.WriteLine("{0},{1}", xmax, ymax); Console.ReadKey(); //New volume Rendering.renderPipeLine volume = new Rendering.renderPipeLine(); int[] voi = new int[] { 101, 909, 101, 909, 0, 800 }; volume.connectData(path, voi); int[] size = volume.getDims(); //Connect new rendering window vtkRenderWindow renWin = vtkRenderWindow.New(); volume.connectWindow(renWin); volume.updateCurrent(new int[] { 500, 500, 150 }, 1, new int[] { 0, 200 }); //Render //volume.renderImage(); //Segment BCInterface //Segmentation reange int[] extent = new int[] { 0, 767, 0, 767, 0, 767 }; //Segmentation List <vtkImageData> outputs = new List <vtkImageData>(); IO.segmentation_pipeline(out outputs, volume, new int[] { 768, 768, 1 }, extent, new int[] { 0 }, 16); //Suppress false positives Console.WriteLine("Suppressing false positives"); vtkImageData newmask1 = Processing.SWFPSuppression(outputs.ElementAt(0), extent); volume.connectMaskFromData(newmask1); vtkImageData I1 = volume.getVOI(new int[] { 0, 767, 500, 500, 0, 799 }); vtkImageData I2 = volume.getMaskVOI(new int[] { 0, 767, 500, 500, 0, 799 }); byte[] B1 = DataTypes.vtkToByte(I1); byte[] B2 = DataTypes.vtkToByte(I2); Mat image = new Mat(800, 768, MatType.CV_8UC1, B1); Mat image_mask = new Mat(800, 768, MatType.CV_8UC1, B2); using (var window = new Window("window", image: image, flags: WindowMode.AutoSize)) { Cv2.WaitKey(); } using (var window = new Window("window", image: image_mask, flags: WindowMode.AutoSize)) { Cv2.WaitKey(); } Console.ReadKey(); }