diff --git a/3DHistoGrading/3DHistoGrading.csproj b/3DHistoGrading/3DHistoGrading.csproj index c5eb21a..8cbd70d 100644 --- a/3DHistoGrading/3DHistoGrading.csproj +++ b/3DHistoGrading/3DHistoGrading.csproj @@ -100,6 +100,7 @@ + Form @@ -109,6 +110,9 @@ + + MainForm.cs + ResXFileCodeGenerator Resources.Designer.cs diff --git a/3DHistoGrading/Components/Functions.cs b/3DHistoGrading/Components/Functions.cs index 051e7ac..77e3e78 100644 --- a/3DHistoGrading/Components/Functions.cs +++ b/3DHistoGrading/Components/Functions.cs @@ -116,6 +116,7 @@ public static vtkImageData volumeSlicer(vtkImageData volume, int[] sliceN, int a //slicer.Update(); //Return copy of the slice + return permuter.GetOutput(); } diff --git a/3DHistoGrading/Components/Interaction.cs b/3DHistoGrading/Components/Interaction.cs new file mode 100644 index 0000000..384adf9 --- /dev/null +++ b/3DHistoGrading/Components/Interaction.cs @@ -0,0 +1,52 @@ +using System; +using System.IO; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Kitware.VTK; + +namespace HistoGrading.Components +{ + class Interaction + { + //Declarations + static vtkRenderWindow renWin; + + //Public methods + public void set_renderer(vtkRenderWindow input_renwin) + { + renWin = input_renwin; + } + public vtkRenderWindowInteractor coordinate_interactor() + { + //Declare new interactor style + vtkInteractorStyle interactorSyle = vtkInteractorStyle.New(); + + //Set new mouse events + interactorSyle.LeftButtonPressEvt += null; + interactorSyle.LeftButtonReleaseEvt += new vtkObject.vtkObjectEventHandler(get_coordinates); + + //Create new interactor + vtkRenderWindowInteractor interactor = vtkRenderWindowInteractor.New(); + interactor.SetInteractorStyle(interactorSyle); + + return interactor; + } + + //Interactors + private static void get_coordinates(vtkObject sender, vtkObjectEventArgs e) + { + int[] cur = renWin.GetPosition(); + string txt = ""; + foreach(int num in cur) + { + txt += System.String.Format("{0}",num); + txt += "|"; + } + StreamWriter file = new StreamWriter(@"C:\\users\\jfrondel\\desktop\\GITS\\VTKOUTPUT.txt"); + file.WriteLine(txt); + } + } +} diff --git a/3DHistoGrading/Components/Rendering.cs b/3DHistoGrading/Components/Rendering.cs index 0ef1ac1..0a47237 100644 --- a/3DHistoGrading/Components/Rendering.cs +++ b/3DHistoGrading/Components/Rendering.cs @@ -159,7 +159,7 @@ public void connectMask(vtkImageData mask) } } - public class imagePipeLine + private class imagePipeLine { //Image variables private vtkImageActor actor = vtkImageActor.New(); @@ -446,5 +446,6 @@ public int[] getDims() } } + } } diff --git a/3DHistoGrading/MainForm.Designer.cs b/3DHistoGrading/MainForm.Designer.cs index a353048..95d17cb 100644 --- a/3DHistoGrading/MainForm.Designer.cs +++ b/3DHistoGrading/MainForm.Designer.cs @@ -28,275 +28,287 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); - this.panel1 = new System.Windows.Forms.Panel(); - this.viewLabel = new System.Windows.Forms.Label(); - this.transverse2Button = new System.Windows.Forms.Button(); - this.transverse1Button = new System.Windows.Forms.Button(); - this.coronalButton = new System.Windows.Forms.Button(); - this.volumeButton = new System.Windows.Forms.Button(); - this.resetButton = new System.Windows.Forms.Button(); - this.label1 = new System.Windows.Forms.Label(); - this.gmaxLabel = new System.Windows.Forms.Label(); - this.gminBar = new System.Windows.Forms.HScrollBar(); - this.gmaxBar = new System.Windows.Forms.HScrollBar(); - this.maskButton = new System.Windows.Forms.Button(); - this.fileButton = new System.Windows.Forms.Button(); - this.panel2 = new System.Windows.Forms.Panel(); - this.maskLabel = new System.Windows.Forms.Label(); - this.fileLabel = new System.Windows.Forms.Label(); - this.sliceBar = new System.Windows.Forms.VScrollBar(); - this.renderWindowControl = new Kitware.VTK.RenderWindowControl(); - this.fileDialog = new System.Windows.Forms.OpenFileDialog(); - this.sliceLabel = new System.Windows.Forms.Label(); - this.tableLayoutPanel1.SuspendLayout(); - this.panel1.SuspendLayout(); - this.panel2.SuspendLayout(); - this.SuspendLayout(); - // - // tableLayoutPanel1 - // - this.tableLayoutPanel1.ColumnCount = 3; - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 150F)); - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 60F)); - this.tableLayoutPanel1.Controls.Add(this.panel1, 0, 1); - this.tableLayoutPanel1.Controls.Add(this.panel2, 0, 0); - this.tableLayoutPanel1.Controls.Add(this.sliceBar, 2, 1); - this.tableLayoutPanel1.Controls.Add(this.renderWindowControl, 1, 1); - this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; - this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); - this.tableLayoutPanel1.Name = "tableLayoutPanel1"; - this.tableLayoutPanel1.RowCount = 2; - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 70F)); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 449F)); - this.tableLayoutPanel1.Size = new System.Drawing.Size(1047, 607); - this.tableLayoutPanel1.TabIndex = 0; - // - // panel1 - // - this.panel1.Controls.Add(this.viewLabel); - this.panel1.Controls.Add(this.transverse2Button); - this.panel1.Controls.Add(this.transverse1Button); - this.panel1.Controls.Add(this.coronalButton); - this.panel1.Controls.Add(this.volumeButton); - this.panel1.Controls.Add(this.resetButton); - this.panel1.Controls.Add(this.label1); - this.panel1.Controls.Add(this.gmaxLabel); - this.panel1.Controls.Add(this.gminBar); - this.panel1.Controls.Add(this.gmaxBar); - this.panel1.Controls.Add(this.maskButton); - this.panel1.Controls.Add(this.fileButton); - this.panel1.Dock = System.Windows.Forms.DockStyle.Fill; - this.panel1.Location = new System.Drawing.Point(3, 73); - this.panel1.Name = "panel1"; - this.panel1.Size = new System.Drawing.Size(144, 531); - this.panel1.TabIndex = 0; - // - // viewLabel - // - this.viewLabel.AutoSize = true; - this.viewLabel.Location = new System.Drawing.Point(9, 217); - this.viewLabel.Name = "viewLabel"; - this.viewLabel.Size = new System.Drawing.Size(37, 17); - this.viewLabel.TabIndex = 10; - this.viewLabel.Text = "View"; - // - // transverse2Button - // - this.transverse2Button.Location = new System.Drawing.Point(6, 351); - this.transverse2Button.Name = "transverse2Button"; - this.transverse2Button.Size = new System.Drawing.Size(132, 32); - this.transverse2Button.TabIndex = 9; - this.transverse2Button.Text = "Transverse, YZ"; - this.transverse2Button.UseVisualStyleBackColor = true; - this.transverse2Button.Click += new System.EventHandler(this.transverse2Button_Click); - // - // transverse1Button - // - this.transverse1Button.Location = new System.Drawing.Point(6, 313); - this.transverse1Button.Name = "transverse1Button"; - this.transverse1Button.Size = new System.Drawing.Size(132, 32); - this.transverse1Button.TabIndex = 8; - this.transverse1Button.Text = "Transverse, XZ"; - this.transverse1Button.UseVisualStyleBackColor = true; - this.transverse1Button.Click += new System.EventHandler(this.transverse1Button_Click); - // - // coronalButton - // - this.coronalButton.Location = new System.Drawing.Point(6, 275); - this.coronalButton.Name = "coronalButton"; - this.coronalButton.Size = new System.Drawing.Size(132, 32); - this.coronalButton.TabIndex = 7; - this.coronalButton.Text = "Coronal"; - this.coronalButton.UseVisualStyleBackColor = true; - this.coronalButton.Click += new System.EventHandler(this.coronalButton_Click); - // - // volumeButton - // - this.volumeButton.Location = new System.Drawing.Point(6, 237); - this.volumeButton.Name = "volumeButton"; - this.volumeButton.Size = new System.Drawing.Size(132, 32); - this.volumeButton.TabIndex = 6; - this.volumeButton.Text = "Volume"; - this.volumeButton.UseVisualStyleBackColor = true; - this.volumeButton.Click += new System.EventHandler(this.volumeButton_Click); - // - // resetButton - // - this.resetButton.Location = new System.Drawing.Point(9, 139); - this.resetButton.Name = "resetButton"; - this.resetButton.Size = new System.Drawing.Size(132, 57); - this.resetButton.TabIndex = 5; - this.resetButton.Text = "Reset Camera"; - this.resetButton.UseVisualStyleBackColor = true; - this.resetButton.Click += new System.EventHandler(this.resetButton_Click); - // - // label1 - // - this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(10, 490); - this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(65, 17); - this.label1.TabIndex = 4; - this.label1.Text = "Gray min"; - // - // gmaxLabel - // - this.gmaxLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.gmaxLabel.AutoSize = true; - this.gmaxLabel.Location = new System.Drawing.Point(10, 439); - this.gmaxLabel.Name = "gmaxLabel"; - this.gmaxLabel.Size = new System.Drawing.Size(68, 17); - this.gmaxLabel.TabIndex = 2; - this.gmaxLabel.Text = "Gray max"; - // - // gminBar - // - this.gminBar.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.gminBar.Location = new System.Drawing.Point(-3, 507); - this.gminBar.Maximum = 255; - this.gminBar.Name = "gminBar"; - this.gminBar.Size = new System.Drawing.Size(147, 24); - this.gminBar.TabIndex = 3; - this.gminBar.Scroll += new System.Windows.Forms.ScrollEventHandler(this.gminBar_Scroll); - // - // gmaxBar - // - this.gmaxBar.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.gmaxBar.Location = new System.Drawing.Point(-3, 456); - this.gmaxBar.Maximum = 255; - this.gmaxBar.Name = "gmaxBar"; - this.gmaxBar.Size = new System.Drawing.Size(147, 24); - this.gmaxBar.TabIndex = 2; - this.gmaxBar.Value = 255; - this.gmaxBar.Scroll += new System.Windows.Forms.ScrollEventHandler(this.gmaxBar_Scroll); - // - // maskButton - // - this.maskButton.Location = new System.Drawing.Point(9, 76); - this.maskButton.Name = "maskButton"; - this.maskButton.Size = new System.Drawing.Size(132, 57); - this.maskButton.TabIndex = 1; - this.maskButton.Text = "Load Mask"; - this.maskButton.UseVisualStyleBackColor = true; - this.maskButton.Click += new System.EventHandler(this.maskButton_Click); - // - // fileButton - // - this.fileButton.Location = new System.Drawing.Point(9, 13); - this.fileButton.Name = "fileButton"; - this.fileButton.Size = new System.Drawing.Size(132, 57); - this.fileButton.TabIndex = 0; - this.fileButton.Text = "Load Volume"; - this.fileButton.UseVisualStyleBackColor = true; - this.fileButton.Click += new System.EventHandler(this.fileButton_Click); - // - // panel2 - // - this.panel2.BackColor = System.Drawing.SystemColors.Control; - this.tableLayoutPanel1.SetColumnSpan(this.panel2, 3); - this.panel2.Controls.Add(this.sliceLabel); - this.panel2.Controls.Add(this.maskLabel); - this.panel2.Controls.Add(this.fileLabel); - this.panel2.Dock = System.Windows.Forms.DockStyle.Fill; - this.panel2.Location = new System.Drawing.Point(3, 3); - this.panel2.Name = "panel2"; - this.panel2.Size = new System.Drawing.Size(1041, 64); - this.panel2.TabIndex = 1; - // - // maskLabel - // - this.maskLabel.AutoSize = true; - this.maskLabel.Location = new System.Drawing.Point(10, 37); - this.maskLabel.Name = "maskLabel"; - this.maskLabel.Size = new System.Drawing.Size(115, 17); - this.maskLabel.TabIndex = 1; - this.maskLabel.Text = "No Mask Loaded"; - // - // fileLabel - // - this.fileLabel.AutoSize = true; - this.fileLabel.Location = new System.Drawing.Point(10, 10); - this.fileLabel.Name = "fileLabel"; - this.fileLabel.Size = new System.Drawing.Size(112, 17); - this.fileLabel.TabIndex = 0; - this.fileLabel.Text = "No Data Loaded"; - // - // sliceBar - // - this.sliceBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left))); - this.sliceBar.Location = new System.Drawing.Point(987, 70); - this.sliceBar.Name = "sliceBar"; - this.sliceBar.Size = new System.Drawing.Size(60, 537); - this.sliceBar.TabIndex = 2; - this.sliceBar.Value = 50; - this.sliceBar.Scroll += new System.Windows.Forms.ScrollEventHandler(this.sliceBar_Scroll); - // - // renderWindowControl - // - this.renderWindowControl.AddTestActors = false; - this.renderWindowControl.Dock = System.Windows.Forms.DockStyle.Fill; - this.renderWindowControl.Location = new System.Drawing.Point(154, 74); - this.renderWindowControl.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); - this.renderWindowControl.Name = "renderWindowControl"; - this.renderWindowControl.Size = new System.Drawing.Size(829, 529); - this.renderWindowControl.TabIndex = 3; - this.renderWindowControl.TestText = null; - this.renderWindowControl.Load += new System.EventHandler(this.renderWindowControl_Load); - // - // fileDialog - // - this.fileDialog.FileName = "openFileDialog1"; - // - // sliceLabel - // - this.sliceLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.sliceLabel.AutoSize = true; - this.sliceLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.sliceLabel.Location = new System.Drawing.Point(599, 37); - this.sliceLabel.Name = "sliceLabel"; - this.sliceLabel.Size = new System.Drawing.Size(80, 25); - this.sliceLabel.TabIndex = 2; - this.sliceLabel.Text = "No data"; - // - // MainForm - // - this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(1047, 607); - this.Controls.Add(this.tableLayoutPanel1); - this.Name = "MainForm"; - this.Text = "CTVisualization"; - this.tableLayoutPanel1.ResumeLayout(false); - this.panel1.ResumeLayout(false); - this.panel1.PerformLayout(); - this.panel2.ResumeLayout(false); - this.panel2.PerformLayout(); - this.ResumeLayout(false); + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.panel1 = new System.Windows.Forms.Panel(); + this.viewLabel = new System.Windows.Forms.Label(); + this.transverse2Button = new System.Windows.Forms.Button(); + this.transverse1Button = new System.Windows.Forms.Button(); + this.coronalButton = new System.Windows.Forms.Button(); + this.volumeButton = new System.Windows.Forms.Button(); + this.resetButton = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.gmaxLabel = new System.Windows.Forms.Label(); + this.gminBar = new System.Windows.Forms.HScrollBar(); + this.gmaxBar = new System.Windows.Forms.HScrollBar(); + this.maskButton = new System.Windows.Forms.Button(); + this.fileButton = new System.Windows.Forms.Button(); + this.panel2 = new System.Windows.Forms.Panel(); + this.sliceLabel = new System.Windows.Forms.Label(); + this.maskLabel = new System.Windows.Forms.Label(); + this.fileLabel = new System.Windows.Forms.Label(); + this.sliceBar = new System.Windows.Forms.VScrollBar(); + this.renderWindowControl = new Kitware.VTK.RenderWindowControl(); + this.fileDialog = new System.Windows.Forms.OpenFileDialog(); + this.voiButton = new System.Windows.Forms.Button(); + this.tableLayoutPanel1.SuspendLayout(); + this.panel1.SuspendLayout(); + this.panel2.SuspendLayout(); + this.SuspendLayout(); + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 3; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 150F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 60F)); + this.tableLayoutPanel1.Controls.Add(this.panel1, 0, 1); + this.tableLayoutPanel1.Controls.Add(this.panel2, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.sliceBar, 2, 1); + this.tableLayoutPanel1.Controls.Add(this.renderWindowControl, 1, 1); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 2; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 70F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 449F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(1143, 759); + this.tableLayoutPanel1.TabIndex = 0; + // + // panel1 + // + this.panel1.Controls.Add(this.voiButton); + this.panel1.Controls.Add(this.viewLabel); + this.panel1.Controls.Add(this.transverse2Button); + this.panel1.Controls.Add(this.transverse1Button); + this.panel1.Controls.Add(this.coronalButton); + this.panel1.Controls.Add(this.volumeButton); + this.panel1.Controls.Add(this.resetButton); + this.panel1.Controls.Add(this.label1); + this.panel1.Controls.Add(this.gmaxLabel); + this.panel1.Controls.Add(this.gminBar); + this.panel1.Controls.Add(this.gmaxBar); + this.panel1.Controls.Add(this.maskButton); + this.panel1.Controls.Add(this.fileButton); + this.panel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.panel1.Location = new System.Drawing.Point(3, 73); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(144, 683); + this.panel1.TabIndex = 0; + // + // viewLabel + // + this.viewLabel.AutoSize = true; + this.viewLabel.Location = new System.Drawing.Point(9, 217); + this.viewLabel.Name = "viewLabel"; + this.viewLabel.Size = new System.Drawing.Size(37, 17); + this.viewLabel.TabIndex = 10; + this.viewLabel.Text = "View"; + // + // transverse2Button + // + this.transverse2Button.Location = new System.Drawing.Point(6, 351); + this.transverse2Button.Name = "transverse2Button"; + this.transverse2Button.Size = new System.Drawing.Size(132, 32); + this.transverse2Button.TabIndex = 9; + this.transverse2Button.Text = "Transverse, YZ"; + this.transverse2Button.UseVisualStyleBackColor = true; + this.transverse2Button.Click += new System.EventHandler(this.transverse2Button_Click); + // + // transverse1Button + // + this.transverse1Button.Location = new System.Drawing.Point(6, 313); + this.transverse1Button.Name = "transverse1Button"; + this.transverse1Button.Size = new System.Drawing.Size(132, 32); + this.transverse1Button.TabIndex = 8; + this.transverse1Button.Text = "Transverse, XZ"; + this.transverse1Button.UseVisualStyleBackColor = true; + this.transverse1Button.Click += new System.EventHandler(this.transverse1Button_Click); + // + // coronalButton + // + this.coronalButton.Location = new System.Drawing.Point(6, 275); + this.coronalButton.Name = "coronalButton"; + this.coronalButton.Size = new System.Drawing.Size(132, 32); + this.coronalButton.TabIndex = 7; + this.coronalButton.Text = "Coronal"; + this.coronalButton.UseVisualStyleBackColor = true; + this.coronalButton.Click += new System.EventHandler(this.coronalButton_Click); + // + // volumeButton + // + this.volumeButton.Location = new System.Drawing.Point(6, 237); + this.volumeButton.Name = "volumeButton"; + this.volumeButton.Size = new System.Drawing.Size(132, 32); + this.volumeButton.TabIndex = 6; + this.volumeButton.Text = "Volume"; + this.volumeButton.UseVisualStyleBackColor = true; + this.volumeButton.Click += new System.EventHandler(this.volumeButton_Click); + // + // resetButton + // + this.resetButton.Location = new System.Drawing.Point(9, 139); + this.resetButton.Name = "resetButton"; + this.resetButton.Size = new System.Drawing.Size(132, 57); + this.resetButton.TabIndex = 5; + this.resetButton.Text = "Reset Camera"; + this.resetButton.UseVisualStyleBackColor = true; + this.resetButton.Click += new System.EventHandler(this.resetButton_Click); + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(10, 642); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(65, 17); + this.label1.TabIndex = 4; + this.label1.Text = "Gray min"; + // + // gmaxLabel + // + this.gmaxLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.gmaxLabel.AutoSize = true; + this.gmaxLabel.Location = new System.Drawing.Point(10, 591); + this.gmaxLabel.Name = "gmaxLabel"; + this.gmaxLabel.Size = new System.Drawing.Size(68, 17); + this.gmaxLabel.TabIndex = 2; + this.gmaxLabel.Text = "Gray max"; + // + // gminBar + // + this.gminBar.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.gminBar.Location = new System.Drawing.Point(-3, 659); + this.gminBar.Maximum = 255; + this.gminBar.Name = "gminBar"; + this.gminBar.Size = new System.Drawing.Size(147, 24); + this.gminBar.TabIndex = 3; + this.gminBar.Scroll += new System.Windows.Forms.ScrollEventHandler(this.gminBar_Scroll); + // + // gmaxBar + // + this.gmaxBar.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.gmaxBar.Location = new System.Drawing.Point(-3, 608); + this.gmaxBar.Maximum = 255; + this.gmaxBar.Name = "gmaxBar"; + this.gmaxBar.Size = new System.Drawing.Size(147, 24); + this.gmaxBar.TabIndex = 2; + this.gmaxBar.Value = 255; + this.gmaxBar.Scroll += new System.Windows.Forms.ScrollEventHandler(this.gmaxBar_Scroll); + // + // maskButton + // + this.maskButton.Location = new System.Drawing.Point(9, 76); + this.maskButton.Name = "maskButton"; + this.maskButton.Size = new System.Drawing.Size(132, 57); + this.maskButton.TabIndex = 1; + this.maskButton.Text = "Load Mask"; + this.maskButton.UseVisualStyleBackColor = true; + this.maskButton.Click += new System.EventHandler(this.maskButton_Click); + // + // fileButton + // + this.fileButton.Location = new System.Drawing.Point(9, 13); + this.fileButton.Name = "fileButton"; + this.fileButton.Size = new System.Drawing.Size(132, 57); + this.fileButton.TabIndex = 0; + this.fileButton.Text = "Load Volume"; + this.fileButton.UseVisualStyleBackColor = true; + this.fileButton.Click += new System.EventHandler(this.fileButton_Click); + // + // panel2 + // + this.panel2.BackColor = System.Drawing.SystemColors.Control; + this.tableLayoutPanel1.SetColumnSpan(this.panel2, 3); + this.panel2.Controls.Add(this.sliceLabel); + this.panel2.Controls.Add(this.maskLabel); + this.panel2.Controls.Add(this.fileLabel); + this.panel2.Dock = System.Windows.Forms.DockStyle.Fill; + this.panel2.Location = new System.Drawing.Point(3, 3); + this.panel2.Name = "panel2"; + this.panel2.Size = new System.Drawing.Size(1137, 64); + this.panel2.TabIndex = 1; + // + // sliceLabel + // + this.sliceLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.sliceLabel.AutoSize = true; + this.sliceLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.sliceLabel.Location = new System.Drawing.Point(599, 37); + this.sliceLabel.Name = "sliceLabel"; + this.sliceLabel.Size = new System.Drawing.Size(80, 25); + this.sliceLabel.TabIndex = 2; + this.sliceLabel.Text = "No data"; + // + // maskLabel + // + this.maskLabel.AutoSize = true; + this.maskLabel.Location = new System.Drawing.Point(10, 37); + this.maskLabel.Name = "maskLabel"; + this.maskLabel.Size = new System.Drawing.Size(115, 17); + this.maskLabel.TabIndex = 1; + this.maskLabel.Text = "No Mask Loaded"; + // + // fileLabel + // + this.fileLabel.AutoSize = true; + this.fileLabel.Location = new System.Drawing.Point(10, 10); + this.fileLabel.Name = "fileLabel"; + this.fileLabel.Size = new System.Drawing.Size(112, 17); + this.fileLabel.TabIndex = 0; + this.fileLabel.Text = "No Data Loaded"; + // + // sliceBar + // + this.sliceBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left))); + this.sliceBar.Location = new System.Drawing.Point(1083, 70); + this.sliceBar.Name = "sliceBar"; + this.sliceBar.Size = new System.Drawing.Size(60, 689); + this.sliceBar.TabIndex = 2; + this.sliceBar.Value = 50; + this.sliceBar.Scroll += new System.Windows.Forms.ScrollEventHandler(this.sliceBar_Scroll); + // + // renderWindowControl + // + this.renderWindowControl.AddTestActors = false; + this.renderWindowControl.Dock = System.Windows.Forms.DockStyle.Fill; + this.renderWindowControl.Location = new System.Drawing.Point(154, 74); + this.renderWindowControl.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.renderWindowControl.Name = "renderWindowControl"; + this.renderWindowControl.Size = new System.Drawing.Size(925, 681); + this.renderWindowControl.TabIndex = 3; + this.renderWindowControl.TestText = null; + this.renderWindowControl.Load += new System.EventHandler(this.renderWindowControl_Load); + // + // fileDialog + // + this.fileDialog.FileName = "openFileDialog1"; + // + // voiButton + // + this.voiButton.Location = new System.Drawing.Point(6, 424); + this.voiButton.Name = "voiButton"; + this.voiButton.Size = new System.Drawing.Size(132, 41); + this.voiButton.TabIndex = 3; + this.voiButton.Text = "Select VOI"; + this.voiButton.UseVisualStyleBackColor = true; + this.voiButton.Click += new System.EventHandler(this.voiButton_Click); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(1143, 759); + this.Controls.Add(this.tableLayoutPanel1); + this.Name = "MainForm"; + this.Text = "CTVisualization"; + this.tableLayoutPanel1.ResumeLayout(false); + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); + this.panel2.ResumeLayout(false); + this.panel2.PerformLayout(); + this.ResumeLayout(false); } @@ -323,6 +335,7 @@ private void InitializeComponent() private System.Windows.Forms.Label viewLabel; private System.Windows.Forms.OpenFileDialog fileDialog; private System.Windows.Forms.Label sliceLabel; -} + private System.Windows.Forms.Button voiButton; + } } diff --git a/3DHistoGrading/MainForm.cs b/3DHistoGrading/MainForm.cs index d656de7..f5039ce 100644 --- a/3DHistoGrading/MainForm.cs +++ b/3DHistoGrading/MainForm.cs @@ -426,5 +426,11 @@ private void gminBar_Scroll(object sender, ScrollEventArgs e) gminBar_ValueChanged(this, null); } } + + + //New Functions + private void voiButton_Click(object sender, EventArgs e) + { + } } } diff --git a/CNTKIntegration/CNTKIntegration.sln b/CNTKIntegration/CNTKIntegration.sln new file mode 100644 index 0000000..642cd06 --- /dev/null +++ b/CNTKIntegration/CNTKIntegration.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27428.2015 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CNTKIntegration", "CNTKIntegration\CNTKIntegration.csproj", "{DF287675-FBD0-4E44-AC82-7A5B3DC9F5B5}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {DF287675-FBD0-4E44-AC82-7A5B3DC9F5B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DF287675-FBD0-4E44-AC82-7A5B3DC9F5B5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DF287675-FBD0-4E44-AC82-7A5B3DC9F5B5}.Debug|x64.ActiveCfg = Debug|x64 + {DF287675-FBD0-4E44-AC82-7A5B3DC9F5B5}.Debug|x64.Build.0 = Debug|x64 + {DF287675-FBD0-4E44-AC82-7A5B3DC9F5B5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DF287675-FBD0-4E44-AC82-7A5B3DC9F5B5}.Release|Any CPU.Build.0 = Release|Any CPU + {DF287675-FBD0-4E44-AC82-7A5B3DC9F5B5}.Release|x64.ActiveCfg = Release|x64 + {DF287675-FBD0-4E44-AC82-7A5B3DC9F5B5}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {7361E0DF-AC8E-4D38-9310-21114107E1CE} + EndGlobalSection +EndGlobal diff --git a/CNTKIntegration/CNTKIntegration/App.config b/CNTKIntegration/CNTKIntegration/App.config new file mode 100644 index 0000000..731f6de --- /dev/null +++ b/CNTKIntegration/CNTKIntegration/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/CNTKIntegration/CNTKIntegration/CNTKIntegration.csproj b/CNTKIntegration/CNTKIntegration/CNTKIntegration.csproj new file mode 100644 index 0000000..6a2f27d --- /dev/null +++ b/CNTKIntegration/CNTKIntegration/CNTKIntegration.csproj @@ -0,0 +1,113 @@ + + + + + + Debug + AnyCPU + {DF287675-FBD0-4E44-AC82-7A5B3DC9F5B5} + Exe + CNTKIntegration + CNTKIntegration + v4.6.1 + 512 + true + + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + + ..\packages\CNTK.CPUOnly.2.5.1\lib\net45\x64\Cntk.Core.Managed-2.5.1.dll + + + ..\packages\Activiz.NET.x64.5.8.0\lib\net20\Kitware.mummy.Runtime.dll + + + ..\packages\Activiz.NET.x64.5.8.0\lib\net20\Kitware.VTK.dll + + + ..\packages\OpenCvSharp3-AnyCPU.3.4.1.20180830\lib\net46\OpenCvSharp.dll + + + ..\packages\OpenCvSharp3-AnyCPU.3.4.1.20180830\lib\net46\OpenCvSharp.Blob.dll + + + ..\packages\OpenCvSharp3-AnyCPU.3.4.1.20180830\lib\net46\OpenCvSharp.Extensions.dll + + + ..\packages\OpenCvSharp3-AnyCPU.3.4.1.20180830\lib\net46\OpenCvSharp.UserInterface.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + \ No newline at end of file diff --git a/CNTKIntegration/CNTKIntegration/Components/DataTypes.cs b/CNTKIntegration/CNTKIntegration/Components/DataTypes.cs new file mode 100644 index 0000000..1593c24 --- /dev/null +++ b/CNTKIntegration/CNTKIntegration/Components/DataTypes.cs @@ -0,0 +1,100 @@ +using System; +using System.IO; +using System.Drawing; +using System.Runtime.InteropServices; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Kitware.VTK; +using OpenCvSharp; +using OpenCvSharp.Extensions; + +namespace CNTKIntegration.Components +{ + class DataTypes + { + //3D byte array to vtkimagedata + public static vtkImageData byteToVTK(byte[,,] data) + { + //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[0] - 1, 0, dims[1] - 1, 0, dims[2] - 1); + //Scalar type + vtkdata.SetScalarTypeToUnsignedChar(); + vtkdata.Update(); + + //Return vtk data + return vtkdata; + } + + //vtkimagedata to 1d byte array + public static byte[] vtkToByte(vtkImageData vtkdata) + { + //Get vtk data dimensions + int[] extent = vtkdata.GetExtent(); + int[] dims = new int[] { extent[1] - extent[0], extent[3] - extent[2], extent[5] - extent[4] }; + //New byte array for conversions + byte[] bytedata = new byte[dims[0] * dims[1] * dims[2]]; + //pin bytedata to memory + GCHandle pinnedArray = GCHandle.Alloc(bytedata, GCHandleType.Pinned); + //Get pointer to pinned array + IntPtr ptr = pinnedArray.AddrOfPinnedObject(); + //VTK exporter + vtkImageExport exporter = vtkImageExport.New(); + //Connect input data to exporter + exporter.SetInput(vtkdata); + exporter.Update(); + //Export data to byte array + exporter.Export(ptr); + //Free pinned array + pinnedArray.Free(); + //Return byte array + return bytedata; + } + + //byte array to float + public static float[] byteToFloat(byte[] bytedata, float mu = (float)0, float sd = (float)0) + { + //Empty array for putput + float[] floatdata = new float[bytedata.Length]; + + //Iterate over bytedata + Parallel.For(0,bytedata.Length, k => + { + //If normalization parameters are not give, return bytedata cast as float data + if (mu == 0) + { + floatdata[k] = (float)bytedata[k]; + } + //Otherwise normalize data + else + { + floatdata[k] = (float)bytedata[k]-mu; + if (sd != 0) + { + floatdata[k] /= sd; + } + } + }); + + //return float data + return floatdata; + } + } +} diff --git a/CNTKIntegration/CNTKIntegration/Components/Functions.cs b/CNTKIntegration/CNTKIntegration/Components/Functions.cs new file mode 100644 index 0000000..727d9d9 --- /dev/null +++ b/CNTKIntegration/CNTKIntegration/Components/Functions.cs @@ -0,0 +1,364 @@ +using System; +using System.IO; +using System.Drawing; +using System.Drawing.Imaging; +using System.Runtime.InteropServices; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Kitware.VTK; +using OpenCvSharp; +using OpenCvSharp.Extensions; + +using CNTKIntegration.Components; + +namespace CNTKIntegration.Components +{ + class Functions + { + //Loader + public static vtkImageData VTKLoader(string path, string extension) + { + /*DEPRECATED!!*/ + //Output + vtkImageData data = vtkImageData.New(); + //Get files from path + DirectoryInfo d = new DirectoryInfo(@path); + FileInfo[] files = d.GetFiles(); + + vtkStringArray allfiles = vtkStringArray.New(); + //Iterate over files and read image data + foreach (FileInfo file in files) + { + //Fullfile + string fullfile = Path.Combine(path, file.Name); + allfiles.InsertNextValue(fullfile); + } + if (extension == ".png") + { + vtkPNGReader reader = vtkPNGReader.New(); + reader.SetFileNames(allfiles); + reader.Update(); + data = reader.GetOutput(); + reader.Dispose(); + } + if (extension == ".jpg") + { + vtkJPEGReader reader = vtkJPEGReader.New(); + reader.SetFileNames(allfiles); + reader.Update(); + data = reader.GetOutput(); + reader.Dispose(); + } + if (extension == ".bmp") + { + vtkBMPReader reader = vtkBMPReader.New(); + reader.SetFileNames(allfiles); + reader.Update(); + data = reader.GetOutput(); + reader.Dispose(); + } + data.SetScalarTypeToUnsignedChar(); + data.Update(); + return data; + } + + //Slicer + public static vtkImageData volumeSlicer(vtkImageData volume, int[] sliceN, int axis) + { + /*Gets a 2D slice from the 3D data*/ + + //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(); + } + + //VOIExtractor + public static float[] voiToFloat(vtkImageData volume, int[] extent, int[] orientation) + { + /*Extracts a VOI from the input volume*/ + + //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 VOI + slicer.SetVOI(extent[0], extent[1], extent[2], extent[3], extent[4], extent[5]); + slicer.Update(); + + //Set orientation + permuter.SetInputConnection(slicer.GetOutputPort()); + permuter.SetFilteredAxes(orientation[0], orientation[1], orientation[2]); + + //Convert VOI to normalized float + float[] floatdata = DataTypes.byteToFloat( + DataTypes.vtkToByte(permuter.GetOutput()), + (float)113.05652141, (float)39.87462853); + + return floatdata; + } + + //Prerocessing + public static vtkImageData scalarCopy(vtkImageData data) + { + /*DEPERCATED!!*/ + //Get data extent + int[] dims = data.GetExtent(); + vtkImageData newdata = vtkImageData.New(); + newdata.SetExtent(dims[0], dims[1], dims[2], dims[3], dims[4], dims[5]); + for (int h = dims[0]; h <= dims[1]; h++) + { + for (int w = dims[2]; w <= dims[3]; w++) + { + for (int d = dims[4]; d <= dims[5]; d++) + { + double scalar = data.GetScalarComponentAsDouble(h, w, d, 0); + newdata.SetScalarComponentFromDouble(h, w, d, 0, scalar); + } + + } + } + return newdata; + } + + public static vtkImageData loadVTK(string path) + { + /*Read all images in folder containing file from given path + *Uses ParaLoader class to get the data in vtk format*/ + + //Declare loader + ParaLoader loader = new ParaLoader(); + //Set input path to loader + loader.setInput(path); + //Load data + loader.Load(); + //Extract data to variable + vtkImageData data = loader.GetData(); + return data; + } + + //Find files + public static List getFiles(string file) + { + /*Find all files which correspond to selected file. + *When reading multiple files, files must start with the same name, which ends in a digit, + *as the selected file and have the same extension.*/ + + //Get file name and extension + string fileName = Path.GetFileName(file); + string extension = Path.GetExtension(file); + + //Get the starting string of the file + //if the files are numbered, the starting string is recorded and used + //to find all files with similar names + + //Empty string + string fstart = ""; + //Length of file name + int nameL = fileName.Length; + //Loop from the start of the extension to start of the file name + //and check for numbers + for (int k = 5; k < nameL; k++) + { + char c = fileName[nameL - k]; + if (Char.IsNumber(c) == false) + { + for (int kk = 0; kk < (nameL - k); kk++) + { + fstart += fileName[kk]; + } + + break; + } + } + + //Get directory info + string path = Path.GetDirectoryName(file); + DirectoryInfo d = new DirectoryInfo(@path); + + //Get all files + FileInfo[] allFiles = d.GetFiles(); + + //Empty list for found files + List names = new List(); + + //Loop over the files and find files corresponding to the selected files + foreach (FileInfo curFile in allFiles) + { + //Length of current file name + int L = curFile.Name.Length; + //Compare to selected file and check if contains numbers/has same extension + if (curFile.Name.StartsWith(fstart) && Char.IsNumber(curFile.Name[L - 5]) && curFile.Name.EndsWith(extension)) + { + names.Add(Path.Combine(path, curFile.Name)); + } + } + + //No numbered files found, use selected image + if (names.Count == 0) + { + names.Add(fileName); + } + + return names; + } + + //Image loader, reads images in parallel + private class ParaLoader + { + //Declarations + + //Empty byte array + byte[,,] data; + //Empty image data + vtkImageData vtkdata = vtkImageData.New(); + //Data dimensiosn + int[] dims = new int[] { 0, 0, 0 }; + //Empty list for files + List files; + + //Set input files + public void setInput(string file) + { + //Get files + files = getFiles(file); + //Read image and get dimensions + Mat _tmp = new Mat(file, ImreadModes.GrayScale); + dims[0] = _tmp.Height; + dims[1] = _tmp.Width; + dims[2] = files.Count; + //Clear temp file + _tmp.Dispose(); + + //Set data extent. Data extent is set, so z-axis is along the + //first dimension, and y-axis is along the last dimension. + //This will be reversed when the data gets converted to vtkImagedata. + data = new byte[dims[2], dims[1], dims[0]]; + } + + //Read image + private void readImage(int idx) + { + //Read image from file idx. The image is read using OpenCV, and converted to Bitmap. + //Bitmap is then read to the bytearray. + Mat _tmp = new Mat(files[idx], ImreadModes.GrayScale); + Bitmap _image = BitmapConverter.ToBitmap(_tmp); + //Lock bits + Rectangle _rect = new Rectangle(0, 0, dims[1], dims[0]); + BitmapData _bmpData = + _image.LockBits(_rect, ImageLockMode.ReadOnly, _image.PixelFormat); + + //Get the address of first line + IntPtr _ptr = _bmpData.Scan0; + + //Declare new array for gray scale values + int _bytes = Math.Abs(_bmpData.Stride) * _bmpData.Height; + byte[] _grayValues = new byte[_bytes]; + + //Copy the rgb values to the new array + Marshal.Copy(_ptr, _grayValues, 0, _bytes); + + //Method for correct pixel mapping + Func mapPixel = GetPixelMapper(_image.PixelFormat, _bmpData.Stride); + + //Read bits to byte array in parallel + //Remember the data orientation + Parallel.For(0, dims[0], (int h) => + { + Parallel.For(0, dims[1], (int w) => + { + data[idx, w, h] = _grayValues[mapPixel(h, w, 0)]; + }); + }); + } + + //Load all images in parallel + public void Load() + { + //Loop over files + Parallel.For(0, dims[2], (int d) => + { + readImage(d); + }); + } + + //Extract data as vtkImageData + public vtkImageData GetData() + { + //Conver byte data to vtkImageData + vtkdata = DataTypes.byteToVTK(data); + return vtkdata; + } + + //Function for correctly mapping the pixel values, copied from CNTK examples + public static Func GetPixelMapper(PixelFormat pixelFormat, int stride) + { + switch (pixelFormat) + { + /* + case PixelFormat.Format32bppArgb: + return (h, w, c) => h * stride + w * 4 + c; // bytes are B-G-R-A + case PixelFormat.Format24bppRgb: + return (h, w, c) => h * stride + w * 3 + c; // bytes are B-G-R + */ + case PixelFormat.Format8bppIndexed: + default: + return (h, w, c) => h * stride + w; + } + } + } + } +} \ No newline at end of file diff --git a/CNTKIntegration/CNTKIntegration/Models/UNet.cs b/CNTKIntegration/CNTKIntegration/Models/UNet.cs new file mode 100644 index 0000000..d680ab3 --- /dev/null +++ b/CNTKIntegration/CNTKIntegration/Models/UNet.cs @@ -0,0 +1,627 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using CNTK; + +using CNTKIntegration.Components; + +namespace CNTKIntegration.Models +{ + class UNet + { + //Network functions + + //Convolution block + private static Function ConvBlock(Variable input_var, int[] kernel_size, int in_channels, int out_channels, float[] W = null, float[] B = null, + string wpath = null, string[] layer_names = null, bool padding = true, bool use_relu = true, bool use_bn = true) + { + Function output_function; + + if (W != null & wpath != null) + { + throw new System.ArgumentException("1 parameter must be null!", "W, wpath"); + } + //If weight path is given, load weight from path. Otherwise use weight from float array W or, initialize new weights. + if (wpath != null) + { + W = weight_fromDisk(wpath, layer_names[0]); + } + //Initialize weights + Parameter weight = make_weight(kernel_size, in_channels, out_channels, W, layer_names[0]); + + //Generate convolution function + Function convW = CNTKLib.Convolution( + /*kernel and input*/ weight, input_var, + /*strides*/ new int[] { 1, 1, in_channels }, + /*sharing*/ new CNTK.BoolVector { true }, + /*padding*/ new CNTK.BoolVector { padding }); + + //Initialize bias + if (wpath != null) + { + B = make_copies(weight_fromDisk(wpath, layer_names[1]), convW.Output.Shape); + } + Parameter bias = make_bias(convW.Output.Shape, B, layer_names[1]); + + //Add bias + Function add = CNTKLib.Plus(convW, bias); + + //Sigmoid + Function sig = CNTKLib.Sigmoid(add); + + if (use_bn == true) + { + //Initialize batch normalization + int[] bns = new int[] { 1, 1 }; + Parameter scale; + Parameter bnbias; + Parameter rm; + Parameter rv; + var n = Constant.Scalar(0.0f, DeviceDescriptor.CPUDevice); + + make_bn_pars(out_channels, add.Output.Shape, out scale, out bnbias, out rm, out rv, wpath, layer_names[0]); + + //Batch normalization + Function bn = CNTKLib.BatchNormalization(add, scale, bnbias, rm, rv, n, true); + + //ReLU + Function relu = CNTKLib.ReLU(bn); + output_function = relu; + } + else + { + if (use_relu == true) + { + //ReLU + Function relu = CNTKLib.ReLU(add); + output_function = relu; + } + else + { + output_function = sig; + } + } + + return output_function; + } + + //Bilinear upsampling + private static Function UpSampling(Variable input_var, int n_channels) + { + //Weight parameters for transposed convolution and smoothing + float[] Wt = new float[2] { (float)1.0, (float)1.0 }; + int[] ksy = new int[2] { 2, 1 }; + int[] ksx = new int[2] { 1, 2 }; + float[] Ws = new float[9] { (float)1 / (4 * 4), (float)1 / (4 * 2), (float)1 / (4 * 4), + (float)1 / (4 * 2), (float)1 / (4 * 1), (float)1 / (4 * 2), + (float)1 / (4 * 4), (float)1 / (4 * 2), (float)1 / (4 * 4)}; + int[] kss = new int[2] { 3, 3 }; + //Initialize weights + Parameter wtransposedy = make_weight(ksy, n_channels, n_channels, from_kernel(Wt, n_channels), "kernel_y"); + Parameter wtransposedx = make_weight(ksx, n_channels, n_channels, from_kernel(Wt, n_channels), "kernel_x"); + Parameter wsmoothing = make_weight(kss, n_channels, n_channels, from_kernel(Ws, n_channels), "kernel_smoothing"); + + //Transposed convolutions + Function tconvy = CNTKLib.ConvolutionTranspose( + /*kernel and input*/ wtransposedy, input_var, + /*strides*/ new int[] { 2, 1, n_channels }, + /*sharing*/ new CNTK.BoolVector { true }, + /*padding*/ new CNTK.BoolVector { false }); + Function tconvx = CNTKLib.ConvolutionTranspose( + /*kernel and input*/ wtransposedx, tconvy, + /*strides*/ new int[] { 1, 2, n_channels }, + /*sharing*/ new CNTK.BoolVector { true }, + /*padding*/ new CNTK.BoolVector { false }); + //Smoothing + Function smooth = CNTKLib.Convolution( + /*kernel and input*/ wsmoothing, tconvx, + /*strides*/ new int[] { 1, 1, n_channels }, + /*sharing*/new bool[] { true }, + /*padding*/ new bool[] { true }); + + return smooth; + + } + + //Concatenation + private static Function cat(Variable feature1, Variable feature2) + { + //Add input feature maps to variablevector + VariableVector vec = new VariableVector(); + vec.Add(feature1); + vec.Add(feature2); + + //Concatenate along last axis + Axis ax = new Axis(2); + + return CNTKLib.Splice(vec, ax); + } + + //Encoder + private static void encoder(Variable features, int[] ks, int in_channels, int out_channels, + out Function down, out Function pooled, string wpath = null, string[] names = null, bool bn = true) + { + //Performs two convolutions, followed by max pooling + + //Layer names + string[] name1 = new string[2]; string[] name2 = new string[2]; + if (wpath != null) + { + name1[0] = names[0]; + name1[1] = names[1]; + name2[0] = names[2]; + name2[1] = names[3]; + } + else + { + name1 = null; + name2 = null; + } + + //Convolution blocks + var block1 = ConvBlock(features, ks, in_channels, out_channels, null, null, wpath, name1, true, true, bn); + var block2 = ConvBlock(block1, ks, out_channels, out_channels, null, null, wpath, name2, true, true, bn); + + //Max pooling + var pooling = CNTKLib.Pooling( + block2.Output, PoolingType.Max, + new int[] { 2, 2 }, new int[] { 2, 2 }, + new bool[] { true }); + + down = block2.Output; + pooled = pooling.Output; + } + + //Decoder + private static void decoder(Variable feature, Variable feature_big, int[] ks, int in_channels, int out_channels, + out Function up, string wpath = null, string[] names = null, bool bn = true) + { + //Layer names + string[] name1 = new string[2]; string[] name2 = new string[2]; + if (wpath != null) + { + name1[0] = names[0]; + name1[1] = names[1]; + name2[0] = names[2]; + name2[1] = names[3]; + } + else + { + name1 = null; + name2 = null; + } + //Concatenation and upsampling + var upsampled = UpSampling(feature, in_channels / 2); + var catted = cat(upsampled.Output, feature_big); + //Convolutions + var block1 = ConvBlock(catted, ks, in_channels, out_channels, null, null, wpath, name1, true, true, bn); + var block2 = ConvBlock(block1.Output, ks, out_channels, out_channels, null, null, wpath, name2, true, true, bn); + + //Max pooling + var pooling = CNTKLib.Pooling( + block2.Output, PoolingType.Max, + new int[] { 2, 2 }, new int[] { 2, 2 }, + new bool[] { true }); + + up = block2.Output; + } + + //Center block + private static void center(Variable features, int[] ks, int in_channels, int out_channels, + out Function center, string wpath = null, string[] names = null, bool bn = false) + { + //Performs two convolutions, followed by max pooling + + //Layer names + string[] name1 = new string[2]; string[] name2 = new string[2]; + if (wpath != null) + { + name1[0] = names[0]; + name1[1] = names[1]; + name2[0] = names[2]; + name2[1] = names[3]; + } + else + { + name1 = null; + name2 = null; + } + + //Convolution blocks + var block1 = ConvBlock(features, ks, in_channels, out_channels, null, null, wpath, name1, true, true, bn); + var block2 = ConvBlock(block1.Output, ks, out_channels, out_channels, null, null, wpath, name2, true, true, bn); + + center = block2.Output; + } + + //Mixer + private static void mixer(Variable features, int[] ks, int in_channels, int out_channels, + out Function mixer, string wpath = null, string[] names = null) + { + //Performs two convolutions, followed by max pooling + + //Layer names + string[] name1 = new string[2]; + if (wpath != null) + { + name1[0] = names[0]; + name1[1] = names[1]; + } + else + { + name1 = null; + } + + //Convolution blocks + var block1 = ConvBlock(features, ks, in_channels, out_channels, null, null, wpath, name1, true, false, false); + + mixer = block1.Output; + } + + //Helper functions for loading the parameters + + //Generates network weights + private static Parameter make_weight(int[] ks, int in_channels, int out_channels, float[] W = null, string name = null) + { + Parameter weight; + //Array for dimensions + int[] dims = new int[ks.Length + 2]; + for (int k = 0; k < ks.Length + 2; k++) + { + //Kernel dimensions + if (k < ks.Length) + { + dims[k] = ks[k]; + } + //Number of feature maps + if (k == ks.Length) + { + dims[k] = in_channels; + } + if (k == ks.Length + 1) + { + dims[k] = out_channels; + } + } + + //Set weight values from float array if given + if (W != null) + { + //Initialize new weight + weight = new Parameter(dims, DataType.Float, CNTKLib.GlorotUniformInitializer(), DeviceDescriptor.CPUDevice, name); + weight = weight_fromFloat(weight, W, dims); + } + else + { + //Initialize new weight + weight = new Parameter(dims, DataType.Float, CNTKLib.GlorotUniformInitializer(), DeviceDescriptor.CPUDevice); + } + + return weight; + } + + //Generates network bias + private static Parameter make_bias(NDShape dims, float[] W = null, string name = null) + { + Parameter bias; + //Make int array of dims + int[] bks = new int[dims.Rank]; + for (int k = 0; k < bks.Length; k++) + { + bks[k] = dims[k]; + } + //Set weight values from float array if given + if (W != null) + { + //Initialize new weight + bias = new Parameter(dims, DataType.Float, CNTKLib.GlorotUniformInitializer(), DeviceDescriptor.CPUDevice, name); + bias = weight_fromFloat(bias, W, bks); + } + else + { + bias = new Parameter(dims, DataType.Float, CNTKLib.GlorotUniformInitializer(), DeviceDescriptor.CPUDevice); + } + + return bias; + } + + //Generates batch normalization parameters + private static void make_bn_pars(int out_channels, NDShape shape, out Parameter w, out Parameter b, out Parameter m, out Parameter v, string wpath = null, string layer_name = null) + { + //Set weight values from float array if given + if (wpath != null) + { + //Generate parameter names + string[] S = layer_name.Split('_'); + string wn = "bn" + S[0] + "_" + S[1] + "_" + "weight"; + string bn = "bn" + S[0] + "_" + S[1] + "_" + "bias"; + string mn = "bn" + S[0] + "_" + S[1] + "_" + "running_mean"; + string vn = "bn" + S[0] + "_" + S[1] + "_" + "running_var"; + //Initialize new weight + w = new Parameter(new int[] { out_channels }, DataType.Float, CNTKLib.GlorotUniformInitializer(), DeviceDescriptor.CPUDevice); + float[] W = make_copies(weight_fromDisk(wpath, wn), shape, true); + w = weight_fromFloat(w, W, new int[] { out_channels }); + //Initialize new bias + b = new Parameter(new int[] { out_channels }, DataType.Float, CNTKLib.GlorotUniformInitializer(), DeviceDescriptor.CPUDevice); + W = make_copies(weight_fromDisk(wpath, bn), shape, true); + b = weight_fromFloat(b, W, new int[] { out_channels }); + //Initialize new running mean + m = new Parameter(new int[] { out_channels }, DataType.Float, CNTKLib.GlorotUniformInitializer(), DeviceDescriptor.CPUDevice); + W = make_copies(weight_fromDisk(wpath, mn), shape, true); + m = weight_fromFloat(m, W, new int[] { out_channels }); + //Initialize new variance + v = new Parameter(new int[] { out_channels }, DataType.Float, CNTKLib.GlorotUniformInitializer(), DeviceDescriptor.CPUDevice); + W = make_copies(weight_fromDisk(wpath, vn), shape, true); + v = weight_fromFloat(v, W, new int[] { out_channels }); + } + else + { + //Initialize new weight + w = new Parameter(new int[] { out_channels }, DataType.Float, CNTKLib.GlorotUniformInitializer(), DeviceDescriptor.CPUDevice); + //Initialize new bias + b = new Parameter(new int[] { out_channels }, DataType.Float, CNTKLib.GlorotUniformInitializer(), DeviceDescriptor.CPUDevice); + //Initialize new running mean + m = new Parameter(new int[] { out_channels }, DataType.Float, CNTKLib.GlorotUniformInitializer(), DeviceDescriptor.CPUDevice); + //Initialize new variance + v = new Parameter(new int[] { out_channels }, DataType.Float, CNTKLib.GlorotUniformInitializer(), DeviceDescriptor.CPUDevice); + } + } + + //Load weights from array + private static Parameter weight_fromFloat(Parameter weight, float[] array, int[] view) + { + //Generate weight array with correct dimensions + NDArrayView nDArray = new NDArrayView(view, array, DeviceDescriptor.CPUDevice); + weight.SetValue(nDArray); + return weight; + } + + //Generate weight array with correct dimensions from given input kernel + private static float[] from_kernel(float[] kernel, int dim) + { + //Total length of new weight array + int K = dim * dim * kernel.Length; + //Empty array for output + float[] outarray = new float[K]; + //Loop over output array + for (int k = 0; k < K; k += kernel.Length * dim + kernel.Length) + { + //Loop over input array + for (int kk = 0; kk < kernel.Length; kk++) + { + outarray[k + kk] = kernel[kk]; + } + } + //Return the array + return outarray; + } + + //Copy bias to match the dimensions of the input + private static float[] make_copies(float[] kernel, NDShape dims, bool swap_axes = false) + { + int K = dims[0] * dims[1]; + float[] outarray = new float[dims[0] * dims[1] * dims[2]]; + if (swap_axes == false) + { + //Loop over number of maps + for (int k = 0; k < dims[2]; k++) + { + //Loop over spatial dimensions + for (int kk = 0; kk < K; kk++) + { + outarray[k * K + kk] = kernel[k]; + } + } + } + else + { + //Loop over number of maps + for (int k = 0; k < K; k++) + { + //Loop over spatial dimensions + for (int kk = 0; kk < dims[2]; kk++) + { + outarray[k * dims[2] + kk] = kernel[kk]; + } + } + } + return outarray; + } + + //Load weight from disk + private static float[] weight_fromDisk(string path, string dsname) + { + float[] output = HDF5Loader.loadH5(path, dsname); + return output; + } + + //Print parameter + private static void print_parameter(Function input) + { + IList pars = input.Parameters(); + foreach (Parameter par in pars) + { + string name = par.Name; + Console.WriteLine(name); + NDArrayView view = par.Value(); + Value wv = new Value(view); + IList> wd = wv.GetDenseData(par); + foreach (IList L in wd) + { + foreach (float v in L) + { + Console.WriteLine(v); + } + } + Console.ReadKey(); + } + } + + //Variable declarations + public static int BW; + public static int[] bdims; + public static string wpath; + static Function model; + static Variable feature; + + //Model initialization + + public void Initialize(int base_width, int[] batch_dims, string weight_path = null, bool use_bn = true) + { + //Network and data parameters + BW = base_width; + bdims = batch_dims; + //Path to weights + wpath = weight_path; + //Input feature + feature = Variable.InputVariable(batch_dims, DataType.Float); + //Create the model + create_model(use_bn); + } + + //Model creation + private static void create_model(bool use_bn = false) + { + Console.WriteLine("Generating UNet.."); + //Parameters + int[] ks = new int[2] { 3, 3 }; + + //Encoding path + + Function down1; + Function pooled1; + string[] namesd1 = new string[] { "down1_0_weight", "down1_0_bias", "down1_1_weight", "down1_1_bias", }; + encoder(feature, ks, 1, BW, out down1, out pooled1, wpath, namesd1, use_bn); + + + Function down2; + Function pooled2; + string[] namesd2 = new string[] { "down2_0_weight", "down2_0_bias", "down2_1_weight", "down2_1_bias", }; + encoder(pooled1, ks, BW, 2 * BW, out down2, out pooled2, wpath, namesd2, use_bn); + + Function down3; + Function pooled3; + string[] namesd3 = new string[] { "down3_0_weight", "down3_0_bias", "down3_1_weight", "down3_1_bias", }; + encoder(pooled2, ks, 2 * BW, 4 * BW, out down3, out pooled3, wpath, namesd3, use_bn); + + Function down4; + Function pooled4; + string[] namesd4 = new string[] { "down4_0_weight", "down4_0_bias", "down4_1_weight", "down4_1_bias", }; + encoder(pooled3, ks, 4 * BW, 8 * BW, out down4, out pooled4, wpath, namesd4, use_bn); + + Function down5; + Function pooled5; + string[] namesd5 = new string[] { "down5_0_weight", "down5_0_bias", "down5_1_weight", "down5_1_bias", }; + encoder(pooled4, ks, 8 * BW, 16 * BW, out down5, out pooled5, wpath, namesd5, use_bn); + + Function down6; + Function pooled6; + string[] namesd6 = new string[] { "down6_0_weight", "down6_0_bias", "down6_1_weight", "down6_1_bias", }; + encoder(pooled5, ks, 16 * BW, 32 * BW, out down6, out pooled6, wpath, namesd6, use_bn); + + //Center block + Function center1; + string[] namesc = new string[] { "center_0_weight", "center_0_bias", "center_1_weight", "center_1_bias", }; + center(pooled6, ks, 32 * BW, 32 * BW, out center1, wpath, namesc, use_bn); + + //Decoding path + + Function up6; + string[] namesu6 = new string[] { "up6_0_weight", "up6_0_bias", "up6_1_weight", "up6_1_bias", }; + decoder(center1, down6, ks, 64 * BW, 16 * BW, out up6, wpath, namesu6, use_bn); + + Function up5; + string[] namesu5 = new string[] { "up5_0_weight", "up5_0_bias", "up5_1_weight", "up5_1_bias", }; + decoder(up6, down5, ks, 32 * BW, 8 * BW, out up5, wpath, namesu5, use_bn); + + Function up4; + string[] namesu4 = new string[] { "up4_0_weight", "up4_0_bias", "up4_1_weight", "up4_1_bias", }; + decoder(up5, down4, ks, 16 * BW, 4 * BW, out up4, wpath, namesu4, use_bn); + + Function up3; + string[] namesu3 = new string[] { "up3_0_weight", "up3_0_bias", "up3_1_weight", "up3_1_bias", }; + decoder(up4, down3, ks, 8 * BW, 2 * BW, out up3, wpath, namesu3, use_bn); + + Function up2; + string[] namesu2 = new string[] { "up2_0_weight", "up2_0_bias", "up2_1_weight", "up2_1_bias", }; + decoder(up3, down2, ks, 4 * BW, 1 * BW, out up2, wpath, namesu2, use_bn); + + Function up1; + string[] namesu1 = new string[] { "up1_0_weight", "up1_0_bias", "up1_1_weight", "up1_1_bias", }; + decoder(up2, down1, ks, 2 * BW, 1 * BW, out up1, wpath, namesu1, use_bn); + + //Output layer + Function unet; + string[] namesm = new string[] { "mixer.weight", "mixer.bias" }; + mixer(up1, new int[] { 1, 1 }, BW, 1, out unet, wpath, namesm); + + model = unet; + + Console.WriteLine("Done!!"); + + } + + //Inference + public float[] Inference(float[] data) + { + //Generate batch from input data + Value inputdata = mapBatch(data); + //Map input array to feature + var inputDataMap = new Dictionary() { { feature, inputdata } }; + //Create output featuremap + var outputDataMap = new Dictionary() { { model.Output, null } }; + //Forward pass + model.Evaluate(inputDataMap, outputDataMap, DeviceDescriptor.CPUDevice); + //Get output + float[] outarray = get_output(outputDataMap, bdims); + + //Save the model + model.Save("C:\\users\\jfrondel\\desktop\\GITS\\cntkunet.model"); + return outarray; + } + + //Method for mapping float array to minibatch + private static Value mapBatch(float[] data) + { + //Map input data to value + Value featureVal = Value.CreateBatch(bdims, data, DeviceDescriptor.CPUDevice); + + return featureVal; + } + + //Method for extracting inference output + private static float[] get_output(Dictionary result, int[] dims) + { + //Get dictionary keys + Dictionary.KeyCollection keys = result.Keys; + //New nested list for output + IList> outlist; + //Get first key + Variable key = keys.First(); + //Data to list + var D = result[key]; + outlist = D.GetDenseData(key); + + //Output array + float[] outarray = new float[dims[0] * dims[1]]; + //Iterator + int c = 0; + //Iterate over list elements and collect to array + foreach (IList item in outlist) + { + foreach (float k in item) + { + outarray[c] = k; + //Increase iterator + c += 1; + } + } + + return outarray; + } + + } +} diff --git a/CNTKIntegration/CNTKIntegration/Program.cs b/CNTKIntegration/CNTKIntegration/Program.cs new file mode 100644 index 0000000..fff0088 --- /dev/null +++ b/CNTKIntegration/CNTKIntegration/Program.cs @@ -0,0 +1,25 @@ +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Kitware.VTK; + +namespace CNTKIntegration +{ + class Program + { + static void Main(string[] args) + { + //Load CTStack + + //Get VOI + + //Load UNet + + //Inference + } + } +} diff --git a/CNTKIntegration/CNTKIntegration/Properties/AssemblyInfo.cs b/CNTKIntegration/CNTKIntegration/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..45f2a64 --- /dev/null +++ b/CNTKIntegration/CNTKIntegration/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("CNTKIntegration")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("CNTKIntegration")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("df287675-fbd0-4e44-ac82-7a5b3dc9f5b5")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/CNTKIntegration/CNTKIntegration/packages.config b/CNTKIntegration/CNTKIntegration/packages.config new file mode 100644 index 0000000..fc55640 --- /dev/null +++ b/CNTKIntegration/CNTKIntegration/packages.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/CNTKUNet/CNTKUNet/CNTKUNet.csproj b/CNTKUNet/CNTKUNet/CNTKUNet.csproj index 0bd1990..b548553 100644 --- a/CNTKUNet/CNTKUNet/CNTKUNet.csproj +++ b/CNTKUNet/CNTKUNet/CNTKUNet.csproj @@ -62,6 +62,12 @@ ..\packages\HDF5DotNet.x64.1.8.9\lib\Net40\HDF5DotNet.dll + + ..\packages\Activiz.NET.x64.5.8.0\lib\net20\Kitware.mummy.Runtime.dll + + + ..\packages\Activiz.NET.x64.5.8.0\lib\net20\Kitware.VTK.dll + ..\packages\OpenCvSharp3-AnyCPU.3.4.1.20180319\lib\net46\OpenCvSharp.dll diff --git a/CNTKUNet/CNTKUNet/Models/UNet.cs b/CNTKUNet/CNTKUNet/Models/UNet.cs index 742b84e..3f92e16 100644 --- a/CNTKUNet/CNTKUNet/Models/UNet.cs +++ b/CNTKUNet/CNTKUNet/Models/UNet.cs @@ -142,7 +142,7 @@ private static Function cat(Variable feature1, Variable feature2) //Encoder private static void encoder(Variable features, int[] ks, int in_channels, int out_channels, - out Function down, out Function pooled, string wpath = null, string[] names = null) + out Function down, out Function pooled, string wpath = null, string[] names = null, bool bn = true) { //Performs two convolutions, followed by max pooling @@ -162,8 +162,8 @@ private static void encoder(Variable features, int[] ks, int in_channels, int ou } //Convolution blocks - var block1 = ConvBlock(features, ks, in_channels, out_channels, null,null, wpath, name1); - var block2 = ConvBlock(block1, ks, out_channels, out_channels, null,null, wpath, name2); + var block1 = ConvBlock(features, ks, in_channels, out_channels, null,null, wpath, name1, true, true, bn); + var block2 = ConvBlock(block1, ks, out_channels, out_channels, null,null, wpath, name2, true, true, bn); //Max pooling var pooling = CNTKLib.Pooling( @@ -177,7 +177,7 @@ private static void encoder(Variable features, int[] ks, int in_channels, int ou //Decoder private static void decoder(Variable feature, Variable feature_big, int[] ks, int in_channels, int out_channels, - out Function up, string wpath = null, string[] names = null) + out Function up, string wpath = null, string[] names = null, bool bn = true) { //Layer names string[] name1 = new string[2]; string[] name2 = new string[2]; @@ -197,8 +197,8 @@ private static void decoder(Variable feature, Variable feature_big, int[] ks, in var upsampled = UpSampling(feature, in_channels/2); var catted = cat(upsampled.Output, feature_big); //Convolutions - var block1 = ConvBlock(catted, ks, in_channels, out_channels, null, null, wpath, name1); - var block2 = ConvBlock(block1.Output, ks, out_channels, out_channels, null, null, wpath, name2); + var block1 = ConvBlock(catted, ks, in_channels, out_channels, null, null, wpath, name1, true, true, bn); + var block2 = ConvBlock(block1.Output, ks, out_channels, out_channels, null, null, wpath, name2, true, true, bn); //Max pooling var pooling = CNTKLib.Pooling( @@ -211,7 +211,7 @@ private static void decoder(Variable feature, Variable feature_big, int[] ks, in //Center block private static void center(Variable features, int[] ks, int in_channels, int out_channels, - out Function center, string wpath = null, string[] names = null) + out Function center, string wpath = null, string[] names = null, bool bn = false) { //Performs two convolutions, followed by max pooling @@ -231,8 +231,8 @@ private static void center(Variable features, int[] ks, int in_channels, int out } //Convolution blocks - var block1 = ConvBlock(features, ks, in_channels, out_channels, null, null, wpath, name1, true, true, true); - var block2 = ConvBlock(block1.Output, ks, out_channels, out_channels, null, null, wpath, name2, true, true, true); + var block1 = ConvBlock(features, ks, in_channels, out_channels, null, null, wpath, name1, true, true, bn); + var block2 = ConvBlock(block1.Output, ks, out_channels, out_channels, null, null, wpath, name2, true, true, bn); center = block2.Output; } @@ -256,7 +256,7 @@ private static void mixer(Variable features, int[] ks, int in_channels, int out_ } //Convolution blocks - var block1 = ConvBlock(features, ks, in_channels, out_channels, null, null, wpath, name1, false, false, false); + var block1 = ConvBlock(features, ks, in_channels, out_channels, null, null, wpath, name1, true, false, false); mixer = block1.Output; } @@ -469,7 +469,7 @@ private static void print_parameter(Function input) //Model initialization - public void Initialize(int base_width, int[] batch_dims, string weight_path = null) + public void Initialize(int base_width, int[] batch_dims, string weight_path = null, bool use_bn = true) { //Network and data parameters BW = base_width; @@ -479,11 +479,11 @@ public void Initialize(int base_width, int[] batch_dims, string weight_path = nu //Input feature feature = Variable.InputVariable(batch_dims, DataType.Float); //Create the model - create_model(); + create_model(use_bn); } //Model creation - private static void create_model() + private static void create_model(bool use_bn = false) { Console.WriteLine("Generating UNet.."); //Parameters @@ -494,64 +494,64 @@ private static void create_model() Function down1; Function pooled1; string[] namesd1 = new string[] {"down1_0_weight", "down1_0_bias", "down1_1_weight", "down1_1_bias", }; - encoder(feature, ks, 1, BW, out down1, out pooled1, wpath, namesd1); + encoder(feature, ks, 1, BW, out down1, out pooled1, wpath, namesd1, use_bn); Function down2; Function pooled2; string[] namesd2 = new string[] { "down2_0_weight", "down2_0_bias", "down2_1_weight", "down2_1_bias", }; - encoder(pooled1, ks, BW, 2 * BW, out down2, out pooled2, wpath, namesd2); + encoder(pooled1, ks, BW, 2 * BW, out down2, out pooled2, wpath, namesd2, use_bn); Function down3; Function pooled3; string[] namesd3 = new string[] { "down3_0_weight", "down3_0_bias", "down3_1_weight", "down3_1_bias", }; - encoder(pooled2, ks, 2 * BW, 4 * BW, out down3, out pooled3, wpath, namesd3); + encoder(pooled2, ks, 2 * BW, 4 * BW, out down3, out pooled3, wpath, namesd3, use_bn); Function down4; Function pooled4; string[] namesd4 = new string[] { "down4_0_weight", "down4_0_bias", "down4_1_weight", "down4_1_bias", }; - encoder(pooled3, ks, 4 * BW, 8 * BW, out down4, out pooled4, wpath, namesd4); + encoder(pooled3, ks, 4 * BW, 8 * BW, out down4, out pooled4, wpath, namesd4, use_bn); Function down5; Function pooled5; string[] namesd5 = new string[] { "down5_0_weight", "down5_0_bias", "down5_1_weight", "down5_1_bias", }; - encoder(pooled4, ks, 8 * BW, 16 * BW, out down5, out pooled5, wpath, namesd5); + encoder(pooled4, ks, 8 * BW, 16 * BW, out down5, out pooled5, wpath, namesd5, use_bn); Function down6; Function pooled6; string[] namesd6 = new string[] { "down6_0_weight", "down6_0_bias", "down6_1_weight", "down6_1_bias", }; - encoder(pooled5, ks, 16 * BW, 32 * BW, out down6, out pooled6, wpath, namesd6); + encoder(pooled5, ks, 16 * BW, 32 * BW, out down6, out pooled6, wpath, namesd6, use_bn); //Center block Function center1; string[] namesc = new string[] { "center_0_weight", "center_0_bias", "center_1_weight", "center_1_bias", }; - center(pooled6, ks, 32 * BW, 32 * BW, out center1, wpath, namesc); + center(pooled6, ks, 32 * BW, 32 * BW, out center1, wpath, namesc, use_bn); //Decoding path Function up6; string[] namesu6 = new string[] { "up6_0_weight", "up6_0_bias", "up6_1_weight", "up6_1_bias", }; - decoder(center1, down6, ks, 64 * BW, 16 * BW, out up6, wpath, namesu6); + decoder(center1, down6, ks, 64 * BW, 16 * BW, out up6, wpath, namesu6, use_bn); Function up5; string[] namesu5 = new string[] { "up5_0_weight", "up5_0_bias", "up5_1_weight", "up5_1_bias", }; - decoder(up6, down5, ks, 32 * BW, 8 * BW, out up5, wpath, namesu5); + decoder(up6, down5, ks, 32 * BW, 8 * BW, out up5, wpath, namesu5, use_bn); Function up4; string[] namesu4 = new string[] { "up4_0_weight", "up4_0_bias", "up4_1_weight", "up4_1_bias", }; - decoder(up5, down4, ks, 16 * BW, 4 * BW, out up4, wpath, namesu4); + decoder(up5, down4, ks, 16 * BW, 4 * BW, out up4, wpath, namesu4, use_bn); Function up3; string[] namesu3 = new string[] { "up3_0_weight", "up3_0_bias", "up3_1_weight", "up3_1_bias", }; - decoder(up4, down3, ks, 8 * BW, 2 * BW, out up3, wpath, namesu3); + decoder(up4, down3, ks, 8 * BW, 2 * BW, out up3, wpath, namesu3, use_bn); Function up2; string[] namesu2 = new string[] { "up2_0_weight", "up2_0_bias", "up2_1_weight", "up2_1_bias", }; - decoder(up3, down2, ks, 4 * BW, 1 * BW, out up2, wpath, namesu2); + decoder(up3, down2, ks, 4 * BW, 1 * BW, out up2, wpath, namesu2, use_bn); Function up1; string[] namesu1 = new string[] { "up1_0_weight", "up1_0_bias", "up1_1_weight", "up1_1_bias", }; - decoder(up2, down1, ks, 2 * BW, 1 * BW, out up1, wpath, namesu1); + decoder(up2, down1, ks, 2 * BW, 1 * BW, out up1, wpath, namesu1, use_bn); //Output layer Function unet; diff --git a/CNTKUNet/CNTKUNet/Program.cs b/CNTKUNet/CNTKUNet/Program.cs index 31dc078..1d0a6aa 100644 --- a/CNTKUNet/CNTKUNet/Program.cs +++ b/CNTKUNet/CNTKUNet/Program.cs @@ -23,18 +23,16 @@ class Program static void Main() { //Path to weights - string wpath = "c:\\users\\jfrondel\\Desktop\\GITS\\UNetE3bnf.h5"; + string wpath = "c:\\users\\jfrondel\\Desktop\\GITS\\UNetE3BN.h5"; //Path to test image string impath = "c:\\users\\jfrondel\\desktop\\GITS\\sample.png"; //Image dimensions - int[] dims = new int[] { 384, 384, 1 }; + int[] dims = new int[] { 384,384, 1 }; //Load test image float[,,] imdata = Functions.readImage(impath, dims); - Console.WriteLine(imdata.GetLength(0)); - Console.WriteLine(imdata.GetLength(1)); - Console.WriteLine(imdata.GetLength(2)); - //Flatten the data adn normalize + + //Flatten the data and normalize float mu = (float)113.05652141; float sd = (float)39.87462853; float[] dataflat = new float[dims[0]*dims[1]]; for (int k = 0; k < dims[0]; k++) @@ -47,11 +45,14 @@ static void Main() //Declare new model UNet new_unet = new UNet(); //Initialize the model - new_unet.Initialize(24, dims, wpath); + new_unet.Initialize(24, dims, wpath, false); //Inference - float[] output = new_unet.Inference(dataflat); - + float[] output; + output = new_unet.Inference(dataflat); + + + //Convert to byte byte[] outbyte = new byte[dims[0]*dims[1]]; @@ -64,7 +65,7 @@ static void Main() Console.WriteLine("Inference done!"); Functions.writeImage(outbyte, dims); - + Console.ReadKey(); } diff --git a/CNTKUNet/CNTKUNet/packages.config b/CNTKUNet/CNTKUNet/packages.config index 65ecb4b..7ac401f 100644 --- a/CNTKUNet/CNTKUNet/packages.config +++ b/CNTKUNet/CNTKUNet/packages.config @@ -1,5 +1,6 @@  +