Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
mitkPlanarFigureSegmentationController.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 <vtkCellArray.h>
20 #include <vtkImageData.h>
21 #include <vtkPoints.h>
22 #include <vtkPolyData.h>
23 #include <vtkPolygon.h>
24 #include <vtkSmartPointer.h>
25 
26 #include <mitkIOUtil.h>
27 #include <mitkImageAccessByItk.h>
28 #include <mitkImageCast.h>
31 
33  : itk::Object(),
34  m_ReduceFilter(NULL),
35  m_NormalsFilter(NULL),
36  m_DistanceImageCreator(NULL),
37  m_ReferenceImage(NULL),
38  m_SegmentationAsImage(NULL)
39 {
41 }
42 
44 {
45 }
46 
48 {
49  m_ReferenceImage = referenceImage;
50 }
51 
53 {
54  if (planarFigure.IsNull())
55  return;
56 
57  bool newFigure = true;
58  std::size_t indexOfFigure = 0;
59  for (std::size_t i = 0; i < m_PlanarFigureList.size(); i++)
60  {
61  if (m_PlanarFigureList.at(i) == planarFigure)
62  {
63  indexOfFigure = i;
64  newFigure = false;
65  break;
66  }
67  }
68 
69  mitk::Surface::Pointer figureAsSurface = NULL;
70 
71  if (newFigure)
72  {
73  m_PlanarFigureList.push_back(planarFigure);
74  figureAsSurface = this->CreateSurfaceFromPlanarFigure(planarFigure);
75  m_SurfaceList.push_back(figureAsSurface);
76  if (!m_PlanarFigureList.empty())
77  {
78  indexOfFigure = m_PlanarFigureList.size() - 1;
79  }
80  }
81  else
82  {
83  figureAsSurface = this->CreateSurfaceFromPlanarFigure(planarFigure);
84  m_SurfaceList.at(indexOfFigure) = figureAsSurface;
85  }
86 
87  if (m_ReduceFilter.IsNull())
88  {
89  InitializeFilters();
90  }
91 
92  m_ReduceFilter->SetInput(indexOfFigure, figureAsSurface);
93 
94  m_NormalsFilter->SetInput(indexOfFigure, m_ReduceFilter->GetOutput(indexOfFigure));
95  m_DistanceImageCreator->SetInput(indexOfFigure, m_NormalsFilter->GetOutput(indexOfFigure));
96 }
97 
99 {
100  if (planarFigure.IsNull())
101  return;
102 
103  bool figureFound = false;
104  std::size_t indexOfFigure = 0;
105  for (std::size_t i = 0; i < m_PlanarFigureList.size(); i++)
106  {
107  if (m_PlanarFigureList.at(i) == planarFigure)
108  {
109  indexOfFigure = i;
110  figureFound = true;
111  break;
112  }
113  }
114 
115  if (!figureFound)
116  return;
117 
118  PlanarFigureListType::iterator whereIter = m_PlanarFigureList.begin();
119  whereIter += indexOfFigure;
120  m_PlanarFigureList.erase(whereIter);
121 
122  SurfaceListType::iterator surfaceIter = m_SurfaceList.begin();
123  surfaceIter += indexOfFigure;
124  m_SurfaceList.erase(surfaceIter);
125 
126  // TODO: fix this! The following code had to be removed as the method
127  // RemoveInputs() has been removed in ITK 4
128  // The remaining code works correctly but is slower
129  if (false && indexOfFigure == m_PlanarFigureList.size() - 1)
130  {
131  // Ff the removed figure was the last one in the list, we can simply
132  // remove the last input from each filter.
133  // m_DistanceImageCreator->RemoveInputs( m_NormalsFilter->GetOutput( indexOfFigure ) );
134  // m_NormalsFilter->RemoveInput( m_ReduceFilter->GetOutput( indexOfFigure ) );
135  // m_ReduceFilter->RemoveInput( const_cast<mitk::Surface*>(m_ReduceFilter->GetInput(indexOfFigure)) );
136  }
137  else
138  {
139  // this is not very nice! If the figure that has been removed is NOT the last
140  // one in the list we have to create new filters and add all remaining
141  // inputs again.
142  //
143  // Has to be done as the filters do not work when removing an input
144  // other than the last one.
145 
146  // create new filters
147  InitializeFilters();
148 
149  // and add all existing surfaces
150  SurfaceListType::iterator surfaceIter = m_SurfaceList.begin();
151  int index = 0;
152  for (surfaceIter = m_SurfaceList.begin(); surfaceIter != m_SurfaceList.end(); surfaceIter++)
153  {
154  m_ReduceFilter->SetInput(index, (*surfaceIter));
155  m_NormalsFilter->SetInput(index, m_ReduceFilter->GetOutput(index));
156  m_DistanceImageCreator->SetInput(index, m_NormalsFilter->GetOutput(index));
157 
158  ++index;
159  }
160  }
161 }
162 
163 template <typename TPixel, unsigned int VImageDimension>
164 void mitk::PlanarFigureSegmentationController::GetImageBase(itk::Image<TPixel, VImageDimension> *input,
166 {
167  result = input;
168 }
169 
171 {
172  m_SegmentationAsImage = NULL;
173 
174  if (m_PlanarFigureList.size() == 0)
175  {
176  m_SegmentationAsImage = mitk::Image::New();
177  m_SegmentationAsImage->Initialize(mitk::MakeScalarPixelType<unsigned char>(), *m_ReferenceImage->GetTimeGeometry());
178 
179  return m_SegmentationAsImage;
180  }
181 
183  AccessFixedDimensionByItk_1(m_ReferenceImage.GetPointer(), GetImageBase, 3, itkImage);
184  m_DistanceImageCreator->SetReferenceImage(itkImage.GetPointer());
185 
186  m_ReduceFilter->Update();
187  m_NormalsFilter->Update();
188  m_DistanceImageCreator->Update();
189 
190  mitk::Image::Pointer distanceImage = m_DistanceImageCreator->GetOutput();
191 
192  // Cleanup the pipeline
193  distanceImage->DisconnectPipeline();
194  m_DistanceImageCreator = NULL;
195  m_NormalsFilter = NULL;
196  m_ReduceFilter = NULL;
197  itkImage = NULL;
198 
199  // If this bool flag is true, the distanceImage will be written to the
200  // filesystem as nrrd-image and as surface-representation.
201  bool debugOutput(false);
202  if (debugOutput)
203  {
204  mitk::IOUtil::Save(distanceImage, "v:/DistanceImage.nrrd");
205  }
206 
208  imageToSurfaceFilter->SetInput(distanceImage);
209  imageToSurfaceFilter->SetThreshold(0);
210  imageToSurfaceFilter->Update();
211 
212  mitk::Surface::Pointer segmentationAsSurface = imageToSurfaceFilter->GetOutput();
213 
214  // Cleanup the pipeline
215  segmentationAsSurface->DisconnectPipeline();
216  imageToSurfaceFilter = NULL;
217 
218  if (debugOutput)
219  {
220  mitk::IOUtil::Save(segmentationAsSurface, "v:/DistanceImageAsSurface.vtk");
221  }
222 
224  surfaceToImageFilter->SetInput(segmentationAsSurface);
225  surfaceToImageFilter->SetImage(m_ReferenceImage);
226  surfaceToImageFilter->SetMakeOutputBinary(true);
227  surfaceToImageFilter->Update();
228 
229  m_SegmentationAsImage = surfaceToImageFilter->GetOutput();
230 
231  // Cleanup the pipeline
232  m_SegmentationAsImage->DisconnectPipeline();
233 
234  return m_SegmentationAsImage;
235 }
236 
239 {
240  if (figure.IsNull())
241  {
242  MITK_ERROR << "Given PlanarFigure is NULL. Please provide valid PlanarFigure.";
243  return NULL;
244  }
245 
247 
248  vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
249  vtkSmartPointer<vtkPolygon> polygon = vtkSmartPointer<vtkPolygon>::New();
250  vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New();
251  vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
252 
253  const mitk::PlaneGeometry *figureGeometry = figure->GetPlaneGeometry();
254 
255  // Get the polyline
256  mitk::PlanarFigure::PolyLineType planarPolyLine = figure->GetPolyLine(0);
257  mitk::PlanarFigure::PolyLineType::iterator iter;
258 
259  // iterate over the polyline, ...
260  int pointCounter = 0;
261  for (iter = planarPolyLine.begin(); iter != planarPolyLine.end(); iter++)
262  {
263  // ... determine the world-coordinates
264  mitk::Point3D pointInWorldCoordiantes;
265  figureGeometry->Map(*iter, pointInWorldCoordiantes);
266 
267  // and add them as new points to the vtkPoints
268  points->InsertNextPoint(pointInWorldCoordiantes[0], pointInWorldCoordiantes[1], pointInWorldCoordiantes[2]);
269  ++pointCounter;
270  }
271 
272  // create a polygon with the points of the polyline
273  polygon->GetPointIds()->SetNumberOfIds(pointCounter);
274  for (int i = 0; i < pointCounter; i++)
275  {
276  polygon->GetPointIds()->SetId(i, i);
277  }
278 
279  // initialize the vtkCellArray and vtkPolyData
280  cells->InsertNextCell(polygon);
281  polyData->SetPoints(points);
282  polyData->SetPolys(cells);
283 
284  // set the polydata to the surface
285  newSurface->SetVtkPolyData(polyData);
286 
287  return newSurface;
288 }
289 
292 {
293  return m_PlanarFigureList;
294 }
295 
297 {
298  m_ReduceFilter = mitk::ReduceContourSetFilter::New();
299  m_ReduceFilter->SetReductionType(ReduceContourSetFilter::NTH_POINT);
300  m_ReduceFilter->SetStepSize(10);
301  m_NormalsFilter = mitk::ComputeContourSetNormalsFilter::New();
302  m_DistanceImageCreator = mitk::CreateDistanceImageFromSurfaceFilter::New();
303 }
static void Save(const mitk::BaseData *data, const std::string &path)
Save a mitk::BaseData instance.
Definition: mitkIOUtil.cpp:824
itk::SmartPointer< Self > Pointer
void SetReferenceImage(Image::Pointer referenceImage)
Setter for the reference image.
void RemovePlanarFigure(mitk::PlanarFigure::Pointer planarFigure)
virtual bool Map(const mitk::Point3D &pt3d_mm, mitk::Point2D &pt2d_mm) const
Project a 3D point given in mm (pt3d_mm) onto the 2D geometry. The result is a 2D point in mm (pt2d_m...
#define MITK_ERROR
Definition: mitkLogMacros.h:24
Image::Pointer GetInterpolationResult()
Performs the interpolation and returns the result as binary image.
void AddPlanarFigure(PlanarFigure::Pointer planarFigure)
Adds a new PlanarFigure to be considered in the interpolation.
void GetImageBase(itk::Image< TPixel, VImageDimension > *input, itk::ImageBase< 3 >::Pointer &result)
static Pointer New()
#define AccessFixedDimensionByItk_1(mitkImage, itkImageTypeFunction, dimension, arg1)
std::vector< PolyLineElement > PolyLineType
Describes a two-dimensional, rectangular plane.
static Pointer New()
static Surface::Pointer CreateSurfaceFromPlanarFigure(PlanarFigure::Pointer figure)
Method to create a surface from a PlanarFigure.
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.