public void SetBitmap() { if (_bitmap == null) { _bitmap = CTSliceHelpers.GetPixelBufferAsBitmap(_ct); _bitmap.Freeze(); _imageBrush = new ImageBrush(); _imageBrush.ImageSource = _bitmap; _ModelGroup = new Model3DGroup(); _ModelGroup.Children.Add(new GeometryModel3D(Tessellate(), new DiffuseMaterial(_imageBrush))); this.Content = _ModelGroup; _3DModel.Children.Add(this); } }
private void ButtonLungs_Click(object sender, RoutedEventArgs e) { bool rc = _scol.BuildSortedSlicesArray(); if (!rc) { System.Windows.MessageBox.Show("There are skips in CTs!"); return; } CTSliceInfo[] slices = _scol.Slices; // Step 1: find the couch int sr = SelectStartSlice(slices); CTSliceInfo ct = slices[sr]; int sc = Couch.DetectCouchInOneSlice(ct.HounsfieldPixelBuffer, ct.RowCount, ct.ColumnCount); int scBefore = Couch.DetectCouchInOneSlice(slices[sr + 10].HounsfieldPixelBuffer, slices[sr + 10].RowCount, slices[sr + 10].ColumnCount); int scAfter = Couch.DetectCouchInOneSlice(slices[sr - 10].HounsfieldPixelBuffer, slices[sr - 10].RowCount, slices[sr - 10].ColumnCount); sc = Math.Max(Math.Max(sc, scBefore), scAfter); // Step 2: Gaussian blur GaussBlur gb = new GaussBlur((float)ct.PixelSpacing_X, (float)ct.PixelSpacing_X, 5); for (int k = 0; k != slices.Length; ++k) { ct = slices[k]; short[,] bm = CTSliceHelpers.Apply(ct, gb); ct.HounsfieldPixelBuffer = bm; } // Step 3: clear below the couch for (int k = 0; k != slices.Length; ++k) { ct = slices[k]; short[,] hb = ct.HounsfieldPixelBuffer; for (int r = ct.RowCount - 1; r > sc; --r) { for (int c = 0; c != ct.ColumnCount; ++c) { hb[r, c] = -1024; } } } // Step 4: gray level thresholding for (int k = 0; k != slices.Length; ++k) { ct = slices[k]; Couch.GLThresholding(ct, sc, -499, 0, -499); } // Step 5: Flool fill for (int k = 0; k != slices.Length; ++k) { ct = slices[k]; short[,] ret = Couch.FloodFill(ct.HounsfieldPixelBuffer, ct.RowCount, ct.ColumnCount, 3, 3, -499, 0); ct.HounsfieldPixelBuffer = ret; } // Step 6: Contours via Moore Neighbour for (int k = slices.Length - 1; k >= slices.Length - 2; --k) { ct = slices[k]; int nr = ct.RowCount; int nc = ct.ColumnCount; int z = ct.SliceLoc; double zz = ct.UpperLeft_Z; short[,] bm = ct.HounsfieldPixelBuffer; bool[,] image = new bool[nr, nc]; for (int r = 0; r != nr; ++r) { for (int c = 0; c != nc; ++c) { image[r, c] = false; if (bm[r, c] < 0) { image[r, c] = true; } } } System.Drawing.Point[] contour = MooreContour.Trace(image, nr, nc); foreach (var pt in contour) { int r = pt.Y; int c = pt.X; bm[r, c] = 500; } } }
// Helper method to handle the selection change event of the IOD Tree. // a) In case the selected tree node represents only group information (Patient, SOPClass, Study, Series), the detailed view is cleared. // b) In case the selected tree node represents an IOD, the DICOM Metainformation is displayed in the DICOM Tag Tree. // c) In case the selected tree node represents a CT Slice, in addition to the DICOM Metainformation, // the ImageFlow button, the volume buttons and the bitmap is shown. private void mIODTree_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs <object> e) { TreeViewItem aSelectedNode = _IODTree.SelectedItem as TreeViewItem; if (aSelectedNode == null) { return; } // Clear old content _DICOMTagTree.Items.Clear(); _Grid.RowDefinitions.First().Height = new GridLength(0); _Grid.RowDefinitions.Last().Height = new GridLength(0); IOD anIOD = aSelectedNode.Tag as IOD; if (anIOD == null) { return; } // Set the FileName as root node string aFileName = Path.GetFileName(anIOD.FileName); TreeViewItem rootNode = new TreeViewItem() { Header = string.Format("File: {0}", aFileName) }; _DICOMTagTree.Items.Add(rootNode); // Expand the root node rootNode.IsExpanded = true; // Add all DICOM attributes to the tree foreach (XElement xe in anIOD.XDocument.Descendants("DataSet").First().Elements("DataElement")) { AddDICOMAttributeToTree(rootNode, xe); } // In case the IOD does have a processable pixel data, the ImageFlow button, the volume buttons and the bitmap is shown. // Otherwise, only the DICOM attributes are shown and the first and last grid row is hided. if (anIOD.IsPixelDataProcessable()) { CTSliceInfo ct = _scol.Retrieve(anIOD.FileName); if (ct == null) { ct = new Helper.CTSliceInfo(anIOD.XDocument, anIOD.FileName); _scol.Add(ct); } _Grid.RowDefinitions.First().Height = new GridLength(30); _Grid.RowDefinitions.Last().Height = new GridLength(ct.RowCount + 16); _Image.Source = CTSliceHelpers.GetPixelBufferAsBitmap(ct); _curCT = ct; } else { _Grid.RowDefinitions.First().Height = new GridLength(0); _Grid.RowDefinitions.Last().Height = new GridLength(0); _curCT = null; } }