Medical Imaging Interaction Toolkit  2018.4.99-c7ee88da
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 (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
14 
15 #include <mitkContourModelSet.h>
16 #include <mitkContourModelUtils.h>
17 #include <mitkExtractSliceFilter.h>
18 #include <mitkImageWriteAccessor.h>
19 #include <mitkProgressBar.h>
20 #include <mitkTimeHelper.h>
21 
22 #include <mitkVtkImageOverwrite.h>
23 
25  : m_MakeOutputBinary(true), m_TimeStep(0), m_ReferenceImage(nullptr)
26 {
27  // Create the output.
28  itk::DataObject::Pointer output = this->MakeOutput(0);
29  Superclass::SetNumberOfRequiredInputs(1);
30  Superclass::SetNumberOfRequiredOutputs(1);
31  Superclass::SetNthOutput(0, output);
32 }
33 
35 {
36 }
37 
39 {
40  mitk::Image *output = this->GetOutput();
41  if ((output->IsInitialized() == false))
42  return;
43 
44  GenerateTimeInInputRegion(output, const_cast<mitk::Image *>(m_ReferenceImage));
45 }
46 
48 {
49  mitk::Image::Pointer output = this->GetOutput();
50 
51  itkDebugMacro(<< "GenerateOutputInformation()");
52 
53  if ((m_ReferenceImage == nullptr) || (m_ReferenceImage->IsInitialized() == false) ||
54  (m_ReferenceImage->GetTimeGeometry() == nullptr))
55  return;
56 
58  {
59  output->Initialize(mitk::MakeScalarPixelType<unsigned char>(), *m_ReferenceImage->GetTimeGeometry(), 1, 1);
60  }
61  else
62  {
64  }
65 
66  output->SetPropertyList(m_ReferenceImage->GetPropertyList()->Clone());
67 }
68 
69 itk::DataObject::Pointer mitk::ContourModelSetToImageFilter::MakeOutput(DataObjectPointerArraySizeType /*idx*/)
70 {
71  return OutputType::New().GetPointer();
72 }
73 
75 {
76  itkDebugMacro("MakeOutput(" << name << ")");
77  if (this->IsIndexedOutputName(name))
78  {
79  return this->MakeOutput(this->MakeIndexFromOutputName(name));
80  }
81  return OutputType::New().GetPointer();
82 }
83 
85 {
86  if (this->GetNumberOfInputs() < 1)
87  {
88  return nullptr;
89  }
90 
91  return static_cast<const mitk::ContourModelSet *>(this->ProcessObject::GetInput(0));
92 }
93 
95 {
96  // Process object is not const-correct so the const_cast is required here
97  this->ProcessObject::SetNthInput(0, const_cast<mitk::ContourModelSet *>(input));
98 }
99 
101 {
102  m_ReferenceImage = refImage;
103 }
104 
106 {
107  return m_ReferenceImage;
108 }
109 
111 {
112  auto *contourSet = const_cast<mitk::ContourModelSet *>(this->GetInput());
113 
114  // Initializing progressbar
115  unsigned int num_contours = contourSet->GetContourModelList()->size();
117 
118  // Assure that the volume data of the output is set (fill volume with zeros)
119  this->InitializeOutputEmpty();
120 
121  mitk::Image::Pointer outputImage = const_cast<mitk::Image *>(this->GetOutput());
122 
123  if (outputImage.IsNull() || outputImage->IsInitialized() == false || !outputImage->IsVolumeSet(m_TimeStep))
124  {
125  MITK_ERROR << "Error creating output for specified image!";
126  return;
127  }
128 
129  if (!contourSet || contourSet->GetContourModelList()->size() == 0)
130  {
131  MITK_ERROR << "No contours specified!";
132  return;
133  }
134 
135  mitk::BaseGeometry *outputImageGeo = outputImage->GetGeometry(m_TimeStep);
136 
137  // Create mitkVtkImageOverwrite which is needed to write the slice back into the volume
138  vtkSmartPointer<mitkVtkImageOverwrite> reslice = vtkSmartPointer<mitkVtkImageOverwrite>::New();
139 
140  // Create ExtractSliceFilter for extracting the corresponding slices from the volume
142  extractor->SetInput(outputImage);
143  extractor->SetTimeStep(m_TimeStep);
144  extractor->SetResliceTransformByGeometry(outputImageGeo);
145 
146  // Fill each contour of the contourmodelset into the image
147  auto it = contourSet->Begin();
148  auto end = contourSet->End();
149  while (it != end)
150  {
151  mitk::ContourModel *contour = it->GetPointer();
152 
153  // 1. Create slice geometry using the contour points
155  mitk::Point3D point3D, tempPoint;
156  mitk::Vector3D normal;
157 
158  mitk::Image::Pointer slice;
159 
160  int sliceIndex;
161  bool isFrontside = true;
162  bool isRotated = false;
163 
164  // Determine plane orientation
165  point3D = contour->GetVertexAt(0)->Coordinates;
166  tempPoint = contour->GetVertexAt(contour->GetNumberOfVertices() * 0.25)->Coordinates;
167  mitk::Vector3D vec = point3D - tempPoint;
168  vec.Normalize();
169  outputImageGeo->WorldToIndex(point3D, point3D);
170 
172  if (mitk::Equal(vec[0], 0))
173  {
174  orientation = mitk::PlaneGeometry::Sagittal;
175  sliceIndex = point3D[0];
176  }
177  else if (mitk::Equal(vec[1], 0))
178  {
179  orientation = mitk::PlaneGeometry::Frontal;
180  sliceIndex = point3D[1];
181  }
182  else if (mitk::Equal(vec[2], 0))
183  {
184  orientation = mitk::PlaneGeometry::Axial;
185  sliceIndex = point3D[2];
186  }
187  else
188  {
189  // TODO Maybe rotate geometry to extract slice?
190  MITK_ERROR
191  << "Cannot detect correct slice number! Only axial, sagittal and frontal oriented contours are supported!";
192  return;
193  }
194 
195  // Initialize plane using the detected orientation
196  plane->InitializeStandardPlane(outputImageGeo, orientation, sliceIndex, isFrontside, isRotated);
197  point3D = plane->GetOrigin();
198  normal = plane->GetNormal();
199  normal.Normalize();
200  point3D += normal * 0.5; // pixelspacing is 1, so half the spacing is 0.5
201  plane->SetOrigin(point3D);
202 
203  // 2. Extract slice at the given position
204  extractor->SetWorldGeometry(plane);
205  extractor->SetVtkOutputRequest(false);
206  reslice->SetOverwriteMode(false);
207 
208  extractor->Modified();
209  extractor->Update();
210 
211  slice = extractor->GetOutput();
212  slice->DisconnectPipeline();
213 
214  // 3. Fill contour into slice
215  mitk::ContourModel::Pointer projectedContour =
216  mitk::ContourModelUtils::ProjectContourTo2DSlice(slice, contour, true, false);
217  mitk::ContourModelUtils::FillContourInSlice(projectedContour, slice, outputImage);
218 
219  // 4. Write slice back into image volume
220  reslice->SetInputSlice(slice->GetVtkImageData());
221 
222  // set overwrite mode to true to write back to the image volume
223  reslice->SetOverwriteMode(true);
224  reslice->Modified();
225 
226  extractor->Modified();
227  extractor->Update();
228 
229  reslice->SetInputSlice(nullptr);
230 
231  // Progress
233 
234  ++it;
235  }
236 
237  outputImage->Modified();
238  outputImage->GetVtkImageData()->Modified();
239 }
240 
242 {
243  // Initialize the output's volume with zeros
244  mitk::Image *output = this->GetOutput();
245  unsigned int byteSize = output->GetPixelType().GetSize();
246 
247  if (output->GetDimension() < 4)
248  {
249  for (unsigned int dim = 0; dim < output->GetDimension(); ++dim)
250  {
251  byteSize *= output->GetDimension(dim);
252  }
253 
254  mitk::ImageWriteAccessor writeAccess(output, output->GetVolumeData(0));
255 
256  memset(writeAccess.GetData(), 0, byteSize);
257  }
258  else
259  {
260  // if we have a time-resolved image we need to set memory to 0 for each time step
261  for (unsigned int dim = 0; dim < 3; ++dim)
262  {
263  byteSize *= output->GetDimension(dim);
264  }
265 
266  for (unsigned int volumeNumber = 0; volumeNumber < output->GetDimension(3); volumeNumber++)
267  {
268  mitk::ImageWriteAccessor writeAccess(output, output->GetVolumeData(volumeNumber));
269 
270  memset(writeAccess.GetData(), 0, byteSize);
271  }
272  }
273 }
int GetNumberOfVertices(int timestep=0) const
Returns the number of vertices at a given timestep.
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...
virtual const VertexType * GetVertexAt(int index, int timestep=0) const
Returns the vertex at the index position within the container.
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.
const mitk::PixelType GetPixelType(int n=0) const
Returns the PixelType of channel n.
Definition: mitkImage.cpp:101
#define MITK_ERROR
Definition: mitkLogMacros.h:20
itk::DataObject::Pointer MakeOutput(DataObjectPointerArraySizeType idx) override
static Pointer New()
static ProgressBar * GetInstance()
static method to get the GUI dependent ProgressBar-instance so the methods for steps to do and progre...
const mitk::TimeGeometry * GetTimeGeometry() const
Return the TimeGeometry of the data as const pointer.
Definition: mitkBaseData.h:61
unsigned int GetDimension() const
Get dimension of the image.
Definition: mitkImage.cpp:106
ContourModelListType * GetContourModelList()
Returns the container of the contours.
virtual ImageDataItemPointer GetVolumeData(int t=0, int n=0, void *data=nullptr, ImportMemoryManagementType importMemoryManagement=CopyMemory) const
Definition: mitkImage.cpp:326
Image class for storing images.
Definition: mitkImage.h:72
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.
void SetImage(const mitk::Image *refImage)
Set the image which will be used to initialize the output of this filter.
void WorldToIndex(const mitk::Point3D &pt_mm, mitk::Point3D &pt_units) const
Convert world coordinates (in mm) of a point to (continuous!) index coordinates.
void GenerateTimeInInputRegion(const mitk::TimeGeometry *outputTimeGeometry, const TOutputRegion &outputRegion, const mitk::TimeGeometry *inputTimeGeometry, TInputRegion &inputRegion)
vcl_size_t GetSize() const
Get size of the PixelType in bytes.
virtual void SetInput(const mitk::ContourModelSet *input)
mitk::PropertyList::Pointer GetPropertyList() const
Get the data&#39;s property list.
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.
virtual bool IsInitialized() const
Check whether the data has been initialized, i.e., at least the Geometry and other header data has be...
static Pointer New()
OutputType * GetOutput()
Get the output data of this image source object.
ImageWriteAccessor class to get locked write-access for a particular image part.
BaseGeometry Describes the geometry of a data object.