Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkContourModelSetToImageFilter.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
18 
19 #include <mitkContourModelSet.h>
20 #include <mitkContourModelUtils.h>
21 #include <mitkExtractSliceFilter.h>
22 #include <mitkImageWriteAccessor.h>
23 #include <mitkProgressBar.h>
24 #include <mitkTimeHelper.h>
25 
26 #include <mitkVtkImageOverwrite.h>
27 
29  : m_MakeOutputBinary(true), m_TimeStep(0), m_ReferenceImage(nullptr)
30 {
31  // Create the output.
32  itk::DataObject::Pointer output = this->MakeOutput(0);
33  Superclass::SetNumberOfRequiredInputs(1);
34  Superclass::SetNumberOfRequiredOutputs(1);
35  Superclass::SetNthOutput(0, output);
36 }
37 
39 {
40 }
41 
43 {
44  mitk::Image *output = this->GetOutput();
45  if ((output->IsInitialized() == false))
46  return;
47 
48  GenerateTimeInInputRegion(output, const_cast<mitk::Image *>(m_ReferenceImage));
49 }
50 
52 {
53  mitk::Image::Pointer output = this->GetOutput();
54 
55  itkDebugMacro(<< "GenerateOutputInformation()");
56 
57  if ((m_ReferenceImage == nullptr) || (m_ReferenceImage->IsInitialized() == false) ||
58  (m_ReferenceImage->GetTimeGeometry() == nullptr))
59  return;
60 
61  if (m_MakeOutputBinary)
62  {
63  output->Initialize(mitk::MakeScalarPixelType<unsigned char>(), *m_ReferenceImage->GetTimeGeometry(), 1, 1);
64  }
65  else
66  {
67  output->Initialize(m_ReferenceImage->GetPixelType(), *m_ReferenceImage->GetTimeGeometry());
68  }
69 
70  output->SetPropertyList(m_ReferenceImage->GetPropertyList()->Clone());
71 }
72 
74 {
75  return OutputType::New().GetPointer();
76 }
77 
79 {
80  itkDebugMacro("MakeOutput(" << name << ")");
81  if (this->IsIndexedOutputName(name))
82  {
83  return this->MakeOutput(this->MakeIndexFromOutputName(name));
84  }
85  return OutputType::New().GetPointer();
86 }
87 
89 {
90  if (this->GetNumberOfInputs() < 1)
91  {
92  return nullptr;
93  }
94 
95  return static_cast<const mitk::ContourModelSet *>(this->ProcessObject::GetInput(0));
96 }
97 
99 {
100  // Process object is not const-correct so the const_cast is required here
101  this->ProcessObject::SetNthInput(0, const_cast<mitk::ContourModelSet *>(input));
102 }
103 
105 {
106  m_ReferenceImage = refImage;
107 }
108 
110 {
111  return m_ReferenceImage;
112 }
113 
115 {
116  mitk::ContourModelSet *contourSet = const_cast<mitk::ContourModelSet *>(this->GetInput());
117 
118  // Initializing progressbar
119  unsigned int num_contours = contourSet->GetContourModelList()->size();
121 
122  // Assure that the volume data of the output is set (fill volume with zeros)
123  this->InitializeOutputEmpty();
124 
125  mitk::Image::Pointer outputImage = const_cast<mitk::Image *>(this->GetOutput());
126 
127  if (outputImage.IsNull() || outputImage->IsInitialized() == false || !outputImage->IsVolumeSet(m_TimeStep))
128  {
129  MITK_ERROR << "Error creating output for specified image!";
130  return;
131  }
132 
133  if (!contourSet || contourSet->GetContourModelList()->size() == 0)
134  {
135  MITK_ERROR << "No contours specified!";
136  return;
137  }
138 
139  mitk::BaseGeometry *outputImageGeo = outputImage->GetGeometry(m_TimeStep);
140 
141  // Create mitkVtkImageOverwrite which is needed to write the slice back into the volume
142  vtkSmartPointer<mitkVtkImageOverwrite> reslice = vtkSmartPointer<mitkVtkImageOverwrite>::New();
143 
144  // Create ExtractSliceFilter for extracting the corresponding slices from the volume
146  extractor->SetInput(outputImage);
147  extractor->SetTimeStep(m_TimeStep);
148  extractor->SetResliceTransformByGeometry(outputImageGeo);
149 
150  // Fill each contour of the contourmodelset into the image
151  auto it = contourSet->Begin();
152  auto end = contourSet->End();
153  while (it != end)
154  {
155  mitk::ContourModel *contour = it->GetPointer();
156 
157  // 1. Create slice geometry using the contour points
159  mitk::Point3D point3D, tempPoint;
160  mitk::Vector3D normal;
161 
162  mitk::Image::Pointer slice;
163 
164  int sliceIndex;
165  bool isFrontside = true;
166  bool isRotated = false;
167 
168  // Determine plane orientation
169  point3D = contour->GetVertexAt(0)->Coordinates;
170  tempPoint = contour->GetVertexAt(contour->GetNumberOfVertices() * 0.25)->Coordinates;
171  mitk::Vector3D vec = point3D - tempPoint;
172  vec.Normalize();
173  outputImageGeo->WorldToIndex(point3D, point3D);
174 
176  if (mitk::Equal(vec[0], 0))
177  {
178  orientation = mitk::PlaneGeometry::Sagittal;
179  sliceIndex = point3D[0];
180  }
181  else if (mitk::Equal(vec[1], 0))
182  {
183  orientation = mitk::PlaneGeometry::Frontal;
184  sliceIndex = point3D[1];
185  }
186  else if (mitk::Equal(vec[2], 0))
187  {
188  orientation = mitk::PlaneGeometry::Axial;
189  sliceIndex = point3D[2];
190  }
191  else
192  {
193  // TODO Maybe rotate geometry to extract slice?
194  MITK_ERROR
195  << "Cannot detect correct slice number! Only axial, sagittal and frontal oriented contours are supported!";
196  return;
197  }
198 
199  // Initialize plane using the detected orientation
200  plane->InitializeStandardPlane(outputImageGeo, orientation, sliceIndex, isFrontside, isRotated);
201  point3D = plane->GetOrigin();
202  normal = plane->GetNormal();
203  normal.Normalize();
204  point3D += normal * 0.5; // pixelspacing is 1, so half the spacing is 0.5
205  plane->SetOrigin(point3D);
206 
207  // 2. Extract slice at the given position
208  extractor->SetWorldGeometry(plane);
209  extractor->SetVtkOutputRequest(false);
210  reslice->SetOverwriteMode(false);
211 
212  extractor->Modified();
213  extractor->Update();
214 
215  slice = extractor->GetOutput();
216  slice->DisconnectPipeline();
217 
218  // 3. Fill contour into slice
219  mitk::ContourModel::Pointer projectedContour =
220  mitk::ContourModelUtils::ProjectContourTo2DSlice(slice, contour, true, false);
221  mitk::ContourModelUtils::FillContourInSlice(projectedContour, slice, outputImage);
222 
223  // 4. Write slice back into image volume
224  reslice->SetInputSlice(slice->GetVtkImageData());
225 
226  // set overwrite mode to true to write back to the image volume
227  reslice->SetOverwriteMode(true);
228  reslice->Modified();
229 
230  extractor->Modified();
231  extractor->Update();
232 
233  reslice->SetInputSlice(nullptr);
234 
235  // Progress
237 
238  ++it;
239  }
240 
241  outputImage->Modified();
242  outputImage->GetVtkImageData()->Modified();
243 }
244 
246 {
247  // Initialize the output's volume with zeros
248  mitk::Image *output = this->GetOutput();
249  unsigned int byteSize = output->GetPixelType().GetSize();
250 
251  if (output->GetDimension() < 4)
252  {
253  for (unsigned int dim = 0; dim < output->GetDimension(); ++dim)
254  {
255  byteSize *= output->GetDimension(dim);
256  }
257 
258  mitk::ImageWriteAccessor writeAccess(output, output->GetVolumeData(0));
259 
260  memset(writeAccess.GetData(), 0, byteSize);
261  }
262  else
263  {
264  // if we have a time-resolved image we need to set memory to 0 for each time step
265  for (unsigned int dim = 0; dim < 3; ++dim)
266  {
267  byteSize *= output->GetDimension(dim);
268  }
269 
270  for (unsigned int volumeNumber = 0; volumeNumber < output->GetDimension(3); volumeNumber++)
271  {
272  mitk::ImageWriteAccessor writeAccess(output, output->GetVolumeData(volumeNumber));
273 
274  memset(writeAccess.GetData(), 0, byteSize);
275  }
276  }
277 }
void Progress(unsigned int steps=1)
Sets the current amount of progress to current progress + steps.
const mitk::ContourModelSet * GetInput(void)
void InitializeOutputEmpty()
Initializes the volume of the output image with zeros.
itk::DataObject::DataObjectIdentifierType DataObjectIdentifierType
ContourModel is a structure of linked vertices defining a contour in 3D space. The vertices are store...
itk::SmartPointer< Self > Pointer
mitk::Point3D Coordinates
Coordinates in 3D space.
static void FillContourInSlice(ContourModel *projectedContour, Image *sliceImage, mitk::Image::Pointer workingImage, int paintingPixelValue=1)
Fill a contour in a 2D slice with a specified pixel value at time step 0.
#define MITK_ERROR
Definition: mitkLogMacros.h:24
virtual itk::DataObject::Pointer MakeOutput(DataObjectPointerArraySizeType idx) override
virtual void GenerateData() override
A version of GenerateData() specific for image processing filters.
static Pointer New()
virtual ContourModelSetIterator Begin()
Return an iterator a the front.
virtual ContourModelSetIterator End()
Return an iterator a the front.
virtual ImageDataItemPointer GetVolumeData(int t=0, int n=0, void *data=nullptr, ImportMemoryManagementType importMemoryManagement=CopyMemory) const
Definition: mitkImage.cpp:330
static ProgressBar * GetInstance()
static method to get the GUI dependent ProgressBar-instance so the methods for steps to do and progre...
vcl_size_t GetSize() const
Get size of the PixelType in bytes.
ContourModelListType * GetContourModelList()
Returns the container of the contours.
Image class for storing images.
Definition: mitkImage.h:76
static ContourModel::Pointer ProjectContourTo2DSlice(Image *slice, ContourModel *contourIn3D, bool correctionForIpSegmentation, bool constrainToInside)
Projects a contour onto an image point by point. Converts from world to index coordinates.
const mitk::PixelType GetPixelType(int n=0) const
Returns the PixelType of channel n.
Definition: mitkImage.cpp:105
void SetImage(const mitk::Image *refImage)
Set the image which will be used to initialize the output of this filter.
void GenerateTimeInInputRegion(const mitk::TimeGeometry *outputTimeGeometry, const TOutputRegion &outputRegion, const mitk::TimeGeometry *inputTimeGeometry, TInputRegion &inputRegion)
virtual void SetInput(const mitk::ContourModelSet *input)
void AddStepsToDo(unsigned int steps)
Adds steps to totalSteps.
MITKNEWMODULE_EXPORT bool Equal(mitk::ExampleDataStructure *leftHandSide, mitk::ExampleDataStructure *rightHandSide, mitk::ScalarType eps, bool verbose)
Returns true if the example data structures are considered equal.
static Pointer New()
virtual bool IsInitialized() const
Check whether the data has been initialized, i.e., at least the Geometry and other header data has be...
ImageWriteAccessor class to get locked write-access for a particular image part.
unsigned int GetDimension() const
Get dimension of the image.
Definition: mitkImage.cpp:110
BaseGeometry Describes the geometry of a data object.
virtual const VertexType * GetVertexAt(int index, int timestep=0) const
Returns the vertex at the index position within the container.
void WorldToIndex(const mitk::Point3D &pt_mm, mitk::Point3D &pt_units) const
Convert world coordinates (in mm) of a point to (continuous!) index coordinates.
int GetNumberOfVertices(int timestep=0) const
Returns the number of vertices at a given timestep.
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.