Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkSurfaceStampImageFilter.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 #include "mitkImageAccessByItk.h"
19 #include "mitkImageWriteAccessor.h"
20 #include "mitkTimeHelper.h"
21 #include <mitkImageCast.h>
22 
23 #include <vtkCell.h>
24 #include <vtkLinearTransform.h>
25 #include <vtkPolyData.h>
26 #include <vtkSmartPointer.h>
27 #include <vtkTransform.h>
28 #include <vtkTransformPolyDataFilter.h>
29 
30 #include <itkTriangleMeshToBinaryImageFilter.h>
31 
33  : m_MakeOutputBinary(false), m_OverwriteBackground(false), m_ForegroundValue(1.0), m_BackgroundValue(0.0)
34 {
35 }
36 
38 {
39 }
40 
42 {
43  mitk::Image *outputImage = this->GetOutput();
44  if ((outputImage->IsInitialized() == false))
45  return;
46 
47  GenerateTimeInInputRegion(outputImage, const_cast<mitk::Image *>(this->GetInput()));
48 }
49 
51 {
52  mitk::Image::ConstPointer inputImage = this->GetInput();
53  mitk::Image::Pointer outputImage = this->GetOutput();
54 
55  itkDebugMacro(<< "GenerateOutputInformation()");
56 
57  if (inputImage.IsNull() || (inputImage->IsInitialized() == false) || (inputImage->GetTimeGeometry() == NULL))
58  return;
59 
60  if (m_MakeOutputBinary)
61  outputImage->Initialize(mitk::MakeScalarPixelType<unsigned char>(), *inputImage->GetTimeGeometry());
62  else
63  outputImage->Initialize(inputImage->GetPixelType(), *inputImage->GetTimeGeometry());
64 
65  outputImage->SetPropertyList(inputImage->GetPropertyList()->Clone());
66 }
67 
69 {
70  m_Surface = surface;
71 }
72 
74 {
75  mitk::Image::ConstPointer inputImage = this->GetInput();
76 
77  if (inputImage.IsNull())
78  return;
79 
80  mitk::Image::Pointer outputImage = this->GetOutput();
81  if (outputImage->IsInitialized() == false)
82  return;
83 
84  if (m_Surface.IsNull())
85  return;
86 
87  mitk::Image::RegionType outputRegion = outputImage->GetRequestedRegion();
88 
89  int tstart = outputRegion.GetIndex(3);
90  int tmax = tstart + outputRegion.GetSize(3);
91 
92  if (tmax > 0)
93  {
94  int t;
95  for (t = tstart; t < tmax; ++t)
96  {
97  this->SurfaceStamp(t);
98  }
99  }
100  else
101  {
102  this->SurfaceStamp(0);
103  }
104 }
105 
107 {
108  mitk::Image::Pointer inputImage = this->GetInput();
109 
110  const mitk::TimeGeometry *surfaceTimeGeometry = GetInput()->GetTimeGeometry();
111  const mitk::TimeGeometry *imageTimeGeometry = inputImage->GetTimeGeometry();
112 
113  // Convert time step from image time-frame to surface time-frame
114  mitk::TimePointType matchingTimePoint = imageTimeGeometry->TimeStepToTimePoint(time);
115  mitk::TimeStepType surfaceTimeStep = surfaceTimeGeometry->TimePointToTimeStep(matchingTimePoint);
116 
117  vtkPolyData *polydata = m_Surface->GetVtkPolyData(surfaceTimeStep);
118  if (!polydata)
119  mitkThrow() << "Polydata is null.";
120 
121  vtkSmartPointer<vtkTransformPolyDataFilter> transformFilter = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
122  transformFilter->SetInputData(polydata);
123  // transformFilter->ReleaseDataFlagOn();
124 
125  vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
126  BaseGeometry::Pointer geometry = surfaceTimeGeometry->GetGeometryForTimeStep(surfaceTimeStep);
127 
128  transform->PostMultiply();
129  transform->Concatenate(geometry->GetVtkTransform()->GetMatrix());
130  // take image geometry into account. vtk-Image information will be changed to unit spacing and zero origin below.
131  BaseGeometry::Pointer imageGeometry = imageTimeGeometry->GetGeometryForTimeStep(time);
132 
133  transform->Concatenate(imageGeometry->GetVtkTransform()->GetLinearInverse());
134  transformFilter->SetTransform(transform);
135  transformFilter->Update();
136 
137  polydata = transformFilter->GetOutput();
138 
139  if (!polydata || !polydata->GetNumberOfPoints())
140  mitkThrow() << "Polydata retrieved from transformation is null or has no points.";
141 
143  mesh->SetCellsAllocationMethod(MeshType::CellsAllocatedDynamicallyCellByCell);
144  unsigned int numberOfPoints = polydata->GetNumberOfPoints();
145  mesh->GetPoints()->Reserve(numberOfPoints);
146 
147  vtkPoints *points = polydata->GetPoints();
148 
149  MeshType::PointType point;
150  for (int i = 0; i < numberOfPoints; i++)
151  {
152  double *aux = points->GetPoint(i);
153  point[0] = aux[0];
154  point[1] = aux[1];
155  point[2] = aux[2];
156  mesh->SetPoint(i, point);
157  }
158 
159  // Load the polygons into the itk::Mesh
160  typedef MeshType::CellAutoPointer CellAutoPointerType;
161  typedef MeshType::CellType CellType;
162  typedef itk::TriangleCell<CellType> TriangleCellType;
163  typedef MeshType::PointIdentifier PointIdentifierType;
164  typedef MeshType::CellIdentifier CellIdentifierType;
165 
166  // Read the number of polygons
167  CellIdentifierType numberOfPolygons = 0;
168  numberOfPolygons = polydata->GetNumberOfPolys();
169  vtkCellArray *polys = polydata->GetPolys();
170 
171  PointIdentifierType numberOfCellPoints = 3;
172  CellIdentifierType i = 0;
173 
174  for (i = 0; i < numberOfPolygons; i++)
175  {
176  vtkIdList *cellIds;
177  vtkCell *vcell = polydata->GetCell(i);
178  cellIds = vcell->GetPointIds();
179 
180  CellAutoPointerType cell;
181  TriangleCellType *triangleCell = new TriangleCellType;
182  PointIdentifierType k;
183  for (k = 0; k < numberOfCellPoints; k++)
184  {
185  triangleCell->SetPointId(k, cellIds->GetId(k));
186  }
187 
188  cell.TakeOwnership(triangleCell);
189  mesh->SetCell(i, cell);
190  }
191 
192  if (!mesh->GetNumberOfPoints())
193  mitkThrow() << "Generated itk mesh is empty.";
194 
195  if (m_MakeOutputBinary)
196  {
197  this->SurfaceStampBinaryOutputProcessing(mesh);
198  }
199  else
200  {
201  AccessFixedDimensionByItk_1(inputImage, SurfaceStampProcessing, 3, mesh);
202  }
203 }
204 
206 {
207  mitk::Image *inputImage = const_cast<mitk::Image *>(this->GetInput());
208 
209  mitk::Image::Pointer outputImage = this->GetOutput();
210 
211  typedef itk::Image<unsigned char, 3> BinaryImageType;
212  BinaryImageType::Pointer itkInputImage;
213  mitk::CastToItkImage(inputImage, itkInputImage);
214 
215  typedef itk::TriangleMeshToBinaryImageFilter<MeshType, BinaryImageType> FilterType;
216 
218  filter->SetInput(mesh);
219  filter->SetInfoImage(itkInputImage);
220  filter->SetInsideValue(1);
221  filter->SetOutsideValue(0);
222  filter->Update();
223 
224  BinaryImageType::Pointer resultImage = filter->GetOutput();
225  resultImage->DisconnectPipeline();
226 
227  mitk::CastToMitkImage(resultImage, outputImage);
228 }
229 
230 template <typename TPixel>
231 void mitk::SurfaceStampImageFilter::SurfaceStampProcessing(itk::Image<TPixel, 3> *input, MeshType *mesh)
232 {
233  typedef itk::Image<TPixel, 3> ImageType;
234  typedef itk::Image<unsigned char, 3> BinaryImageType;
235 
236  typedef itk::TriangleMeshToBinaryImageFilter<mitk::SurfaceStampImageFilter::MeshType, BinaryImageType> FilterType;
237 
239  binaryInput->SetSpacing(input->GetSpacing());
240  binaryInput->SetOrigin(input->GetOrigin());
241  binaryInput->SetDirection(input->GetDirection());
242  binaryInput->SetRegions(input->GetLargestPossibleRegion());
243  binaryInput->Allocate();
244  binaryInput->FillBuffer(0);
245 
247  filter->SetInput(mesh);
248  filter->SetInfoImage(binaryInput);
249  filter->SetInsideValue(1);
250  filter->SetOutsideValue(0);
251  filter->Update();
252 
253  BinaryImageType::Pointer resultImage = filter->GetOutput();
254  resultImage->DisconnectPipeline();
255 
256  mitk::Image::Pointer outputImage = this->GetOutput();
257  typename ImageType::Pointer itkOutputImage;
258  mitk::CastToItkImage(outputImage, itkOutputImage);
259 
260  typedef itk::ImageRegionConstIterator<BinaryImageType> BinaryIteratorType;
261  typedef itk::ImageRegionConstIterator<ImageType> InputIteratorType;
262  typedef itk::ImageRegionIterator<ImageType> OutputIteratorType;
263 
264  BinaryIteratorType sourceIter(resultImage, resultImage->GetLargestPossibleRegion());
265  sourceIter.GoToBegin();
266 
267  InputIteratorType inputIter(input, input->GetLargestPossibleRegion());
268  inputIter.GoToBegin();
269 
270  OutputIteratorType outputIter(itkOutputImage, itkOutputImage->GetLargestPossibleRegion());
271  outputIter.GoToBegin();
272 
273  typename ImageType::PixelType inputValue;
274  unsigned char sourceValue;
275 
276  typename ImageType::PixelType fgValue = static_cast<typename ImageType::PixelType>(m_ForegroundValue);
277  typename ImageType::PixelType bgValue = static_cast<typename ImageType::PixelType>(m_BackgroundValue);
278 
279  while (!sourceIter.IsAtEnd())
280  {
281  sourceValue = static_cast<unsigned char>(sourceIter.Get());
282  inputValue = static_cast<typename ImageType::PixelType>(inputIter.Get());
283 
284  if (sourceValue != 0)
285  outputIter.Set(fgValue);
286  else if (m_OverwriteBackground)
287  outputIter.Set(bgValue);
288  else
289  outputIter.Set(inputValue);
290 
291  ++sourceIter;
292  ++inputIter;
293  ++outputIter;
294  }
295 }
Class for storing surfaces (vtkPolyData).
Definition: mitkSurface.h:32
mitk::Point3D PointType
itk::SmartPointer< Self > Pointer
virtual void GenerateData()
A version of GenerateData() specific for image processing filters.
map::core::discrete::Elements< 3 >::InternalImageType ImageType
void SetSurface(mitk::Surface *surface)
itk::ImageRegion< RegionDimension > RegionType
virtual TimeStepType TimePointToTimeStep(TimePointType timePoint) const =0
Converts a time point to the corresponding time step.
#define mitkThrow()
void SurfaceStampProcessing(itk::Image< TPixel, 3 > *input, MeshType *mesh)
Image class for storing images.
Definition: mitkImage.h:76
virtual TimePointType TimeStepToTimePoint(TimeStepType timeStep) const =0
Converts a time step to a time point.
itk::Image< unsigned char, 3 > BinaryImageType
void SurfaceStampBinaryOutputProcessing(MeshType *mesh)
mitk::ScalarType TimePointType
std::vcl_size_t TimeStepType
void GenerateTimeInInputRegion(const mitk::TimeGeometry *outputTimeGeometry, const TOutputRegion &outputRegion, const mitk::TimeGeometry *inputTimeGeometry, TInputRegion &inputRegion)
itk::QuadEdgeMesh< double, 3 > MeshType
#define AccessFixedDimensionByItk_1(mitkImage, itkImageTypeFunction, dimension, arg1)
void CastToMitkImage(const itk::SmartPointer< ItkOutputImageType > &itkimage, itk::SmartPointer< mitk::Image > &mitkoutputimage)
Cast an itk::Image (with a specific type) to an mitk::Image.
Definition: mitkImageCast.h:78
void MITKCORE_EXPORT CastToItkImage(const mitk::Image *mitkImage, itk::SmartPointer< ItkOutputImageType > &itkOutputImage)
Cast an mitk::Image to an itk::Image with a specific type.
virtual BaseGeometry::Pointer GetGeometryForTimeStep(TimeStepType timeStep) const =0
Returns the geometry which corresponds to the given time step.
virtual bool IsInitialized() const
Check whether the data has been initialized, i.e., at least the Geometry and other header data has be...
unsigned short PixelType
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.