Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkFastMarchingTool3D.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 
17 #include "mitkFastMarchingTool3D.h"
18 #include "mitkToolManager.h"
19 
20 #include "mitkBaseRenderer.h"
21 #include "mitkInteractionConst.h"
22 #include "mitkRenderingManager.h"
23 
24 #include "itkOrImageFilter.h"
25 #include "mitkImageCast.h"
26 #include "mitkImageTimeSelector.h"
27 
28 // us
29 #include <usGetModuleContext.h>
30 #include <usModule.h>
31 #include <usModuleContext.h>
32 #include <usModuleResource.h>
33 
34 namespace mitk
35 {
37 }
38 
40  : /*FeedbackContourTool*/ AutoSegmentationTool(),
41  m_NeedUpdate(true),
42  m_CurrentTimeStep(0),
43  m_LowerThreshold(0),
44  m_UpperThreshold(200),
45  m_StoppingValue(100),
46  m_Sigma(1.0),
47  m_Alpha(-0.5),
48  m_Beta(3.0)
49 {
50 }
51 
53 {
54 }
55 
57 {
58  if (referenceData == NULL)
59  return false;
60 
61  Image *image = dynamic_cast<Image *>(referenceData);
62 
63  if (image == NULL)
64  return false;
65 
66  if (image->GetDimension() < 3)
67  return false;
68 
69  return true;
70 }
71 
73 {
74  return NULL; // mitkFastMarchingTool3D_xpm;
75 }
76 
78 {
80  us::ModuleResource resource = module->GetResource("FastMarching_48x48.png");
81  return resource;
82 }
83 
85 {
86  return "Fast Marching 3D";
87 }
88 
90 {
91  m_UpperThreshold = value / 10.0;
92  m_ThresholdFilter->SetUpperThreshold(m_UpperThreshold);
93  m_NeedUpdate = true;
94 }
95 
97 {
98  m_LowerThreshold = value / 10.0;
99  m_ThresholdFilter->SetLowerThreshold(m_LowerThreshold);
100  m_NeedUpdate = true;
101 }
102 
104 {
105  if (m_Beta != value)
106  {
107  m_Beta = value;
108  m_SigmoidFilter->SetBeta(m_Beta);
109  m_NeedUpdate = true;
110  }
111 }
112 
114 {
115  if (m_Sigma != value)
116  {
117  if (value > 0.0)
118  {
119  m_Sigma = value;
120  m_GradientMagnitudeFilter->SetSigma(m_Sigma);
121  m_NeedUpdate = true;
122  }
123  }
124 }
125 
127 {
128  if (m_Alpha != value)
129  {
130  m_Alpha = value;
131  m_SigmoidFilter->SetAlpha(m_Alpha);
132  m_NeedUpdate = true;
133  }
134 }
135 
137 {
138  if (m_StoppingValue != value)
139  {
140  m_StoppingValue = value;
141  m_FastMarchingFilter->SetStoppingValue(m_StoppingValue);
142  m_NeedUpdate = true;
143  }
144 }
145 
147 {
148  Superclass::Activated();
149 
150  m_ResultImageNode = mitk::DataNode::New();
151  m_ResultImageNode->SetName("FastMarching_Preview");
152  m_ResultImageNode->SetBoolProperty("helper object", true);
153  m_ResultImageNode->SetColor(0.0, 1.0, 0.0);
154  m_ResultImageNode->SetVisibility(true);
155  m_ToolManager->GetDataStorage()->Add(this->m_ResultImageNode, m_ToolManager->GetReferenceData(0));
156 
157  m_SeedsAsPointSet = mitk::PointSet::New();
158  m_SeedsAsPointSetNode = mitk::DataNode::New();
159  m_SeedsAsPointSetNode->SetData(m_SeedsAsPointSet);
160  m_SeedsAsPointSetNode->SetName("3D_FastMarching_PointSet");
161  m_SeedsAsPointSetNode->SetBoolProperty("helper object", true);
162  m_SeedsAsPointSetNode->SetColor(0.0, 1.0, 0.0);
163  m_SeedsAsPointSetNode->SetVisibility(true);
164 
165  // Create PointSetData Interactor
166  m_SeedPointInteractor = mitk::PointSetDataInteractor::New();
167  // Load the according state machine for regular point set interaction
168  m_SeedPointInteractor->LoadStateMachine("PointSet.xml");
169  // Set the configuration file that defines the triggers for the transitions
170  m_SeedPointInteractor->SetEventConfig("PointSetConfig.xml");
171  // set the DataNode (which already is added to the DataStorage
172  m_SeedPointInteractor->SetDataNode(m_SeedsAsPointSetNode);
173 
174  m_ReferenceImageAsITK = InternalImageType::New();
175 
176  m_ProgressCommand = mitk::ToolCommand::New();
177 
178  m_ThresholdFilter = ThresholdingFilterType::New();
179  m_ThresholdFilter->SetLowerThreshold(m_LowerThreshold);
180  m_ThresholdFilter->SetUpperThreshold(m_UpperThreshold);
181  m_ThresholdFilter->SetOutsideValue(0);
182  m_ThresholdFilter->SetInsideValue(1.0);
183 
184  m_SmoothFilter = SmoothingFilterType::New();
185  m_SmoothFilter->AddObserver(itk::ProgressEvent(), m_ProgressCommand);
186  m_SmoothFilter->SetTimeStep(0.05);
187  m_SmoothFilter->SetNumberOfIterations(2);
188  m_SmoothFilter->SetConductanceParameter(9.0);
189 
190  m_GradientMagnitudeFilter = GradientFilterType::New();
191  m_GradientMagnitudeFilter->AddObserver(itk::ProgressEvent(), m_ProgressCommand);
192  m_GradientMagnitudeFilter->SetSigma(m_Sigma);
193 
194  m_SigmoidFilter = SigmoidFilterType::New();
195  m_SigmoidFilter->AddObserver(itk::ProgressEvent(), m_ProgressCommand);
196  m_SigmoidFilter->SetAlpha(m_Alpha);
197  m_SigmoidFilter->SetBeta(m_Beta);
198  m_SigmoidFilter->SetOutputMinimum(0.0);
199  m_SigmoidFilter->SetOutputMaximum(1.0);
200 
201  m_FastMarchingFilter = FastMarchingFilterType::New();
202  m_FastMarchingFilter->AddObserver(itk::ProgressEvent(), m_ProgressCommand);
203  m_FastMarchingFilter->SetStoppingValue(m_StoppingValue);
204 
205  m_SeedContainer = NodeContainer::New();
206  m_SeedContainer->Initialize();
207  m_FastMarchingFilter->SetTrialPoints(m_SeedContainer);
208 
209  // set up pipeline
210  m_SmoothFilter->SetInput(m_ReferenceImageAsITK);
211  m_GradientMagnitudeFilter->SetInput(m_SmoothFilter->GetOutput());
212  m_SigmoidFilter->SetInput(m_GradientMagnitudeFilter->GetOutput());
213  m_FastMarchingFilter->SetInput(m_SigmoidFilter->GetOutput());
214  m_ThresholdFilter->SetInput(m_FastMarchingFilter->GetOutput());
215 
216  m_ToolManager->GetDataStorage()->Add(m_SeedsAsPointSetNode, m_ToolManager->GetWorkingData(0));
217 
220  pointAddedCommand->SetCallbackFunction(this, &mitk::FastMarchingTool3D::OnAddPoint);
221  m_PointSetAddObserverTag = m_SeedsAsPointSet->AddObserver(mitk::PointSetAddEvent(), pointAddedCommand);
222 
225  pointRemovedCommand->SetCallbackFunction(this, &mitk::FastMarchingTool3D::OnDelete);
226  m_PointSetRemoveObserverTag = m_SeedsAsPointSet->AddObserver(mitk::PointSetRemoveEvent(), pointRemovedCommand);
227 
228  this->Initialize();
229 }
230 
232 {
233  m_ToolManager->GetDataStorage()->Remove(this->m_ResultImageNode);
234  m_ToolManager->GetDataStorage()->Remove(this->m_SeedsAsPointSetNode);
235  this->ClearSeeds();
236  this->m_SmoothFilter->RemoveAllObservers();
237  this->m_SigmoidFilter->RemoveAllObservers();
238  this->m_GradientMagnitudeFilter->RemoveAllObservers();
239  this->m_FastMarchingFilter->RemoveAllObservers();
240  m_ResultImageNode = NULL;
242 
243  unsigned int numberOfPoints = m_SeedsAsPointSet->GetSize();
244  for (unsigned int i = 0; i < numberOfPoints; ++i)
245  {
246  mitk::Point3D point = m_SeedsAsPointSet->GetPoint(i);
248  m_SeedsAsPointSet->ExecuteOperation(doOp);
249  }
250  // Deactivate Interaction
251  m_SeedPointInteractor->SetDataNode(NULL);
252  m_ToolManager->GetDataStorage()->Remove(m_SeedsAsPointSetNode);
253  m_SeedsAsPointSetNode = NULL;
254  m_SeedsAsPointSet->RemoveObserver(m_PointSetAddObserverTag);
255  m_SeedsAsPointSet->RemoveObserver(m_PointSetRemoveObserverTag);
256 
257  Superclass::Deactivated();
258 }
259 
261 {
262  m_ReferenceImage = dynamic_cast<mitk::Image *>(m_ToolManager->GetReferenceData(0)->GetData());
263  if (m_ReferenceImage->GetTimeGeometry()->CountTimeSteps() > 1)
264  {
266  timeSelector->SetInput(m_ReferenceImage);
267  timeSelector->SetTimeNr(m_CurrentTimeStep);
268  timeSelector->UpdateLargestPossibleRegion();
269  m_ReferenceImage = timeSelector->GetOutput();
270  }
271  CastToItkImage(m_ReferenceImage, m_ReferenceImageAsITK);
272  m_SmoothFilter->SetInput(m_ReferenceImageAsITK);
273  m_NeedUpdate = true;
274 }
275 
277 {
278  // combine preview image with current working segmentation
279  if (dynamic_cast<mitk::Image *>(m_ResultImageNode->GetData()))
280  {
281  // logical or combination of preview and segmentation slice
282  OutputImageType::Pointer segmentationImageInITK = OutputImageType::New();
283 
284  mitk::Image::Pointer workingImage = dynamic_cast<mitk::Image *>(GetTargetSegmentationNode()->GetData());
285  if (workingImage->GetTimeGeometry()->CountTimeSteps() > 1)
286  {
288  timeSelector->SetInput(workingImage);
289  timeSelector->SetTimeNr(m_CurrentTimeStep);
290  timeSelector->UpdateLargestPossibleRegion();
291  CastToItkImage(timeSelector->GetOutput(), segmentationImageInITK);
292  }
293  else
294  {
295  CastToItkImage(workingImage, segmentationImageInITK);
296  }
297 
298  typedef itk::OrImageFilter<OutputImageType, OutputImageType> OrImageFilterType;
300 
301  orFilter->SetInput(0, m_ThresholdFilter->GetOutput());
302  orFilter->SetInput(1, segmentationImageInITK);
303  orFilter->Update();
304 
305  // set image volume in current time step from itk image
306  workingImage->SetVolume((void *)(m_ThresholdFilter->GetOutput()->GetPixelContainer()->GetBufferPointer()),
307  m_CurrentTimeStep);
308  this->m_ResultImageNode->SetVisibility(false);
309  this->ClearSeeds();
310  workingImage->Modified();
311  }
312 
314  m_ToolManager->ActivateTool(-1);
315 }
316 
318 {
319  // Add a new seed point for FastMarching algorithm
320  mitk::Point3D clickInIndex;
321 
322  m_ReferenceImage->GetGeometry()->WorldToIndex(m_SeedsAsPointSet->GetPoint(m_SeedsAsPointSet->GetSize() - 1),
323  clickInIndex);
324  itk::Index<3> seedPosition;
325  seedPosition[0] = clickInIndex[0];
326  seedPosition[1] = clickInIndex[1];
327  seedPosition[2] = clickInIndex[2];
328 
329  NodeType node;
330  const double seedValue = 0.0;
331  node.SetValue(seedValue);
332  node.SetIndex(seedPosition);
333  this->m_SeedContainer->InsertElement(this->m_SeedContainer->Size(), node);
334  m_FastMarchingFilter->Modified();
335 
337 
338  m_NeedUpdate = true;
339 
340  this->Update();
341 
342  m_ReadyMessage.Send();
343 }
344 
346 {
347  // delete last seed point
348  if (!(this->m_SeedContainer->empty()))
349  {
350  // delete last element of seeds container
351  this->m_SeedContainer->pop_back();
352  m_FastMarchingFilter->Modified();
353 
355 
356  m_NeedUpdate = true;
357 
358  this->Update();
359  }
360 }
361 
363 {
364  const unsigned int progress_steps = 200;
365 
366  if (m_NeedUpdate)
367  {
368  m_ProgressCommand->AddStepsToDo(progress_steps);
369 
370  // remove interaction with poinset while updating
371  m_SeedPointInteractor->SetDataNode(NULL);
372  CurrentlyBusy.Send(true);
373  try
374  {
375  m_ThresholdFilter->Update();
376  }
377  catch (itk::ExceptionObject &excep)
378  {
379  MITK_ERROR << "Exception caught: " << excep.GetDescription();
380 
381  m_ProgressCommand->SetProgress(progress_steps);
382  CurrentlyBusy.Send(false);
383 
384  std::string msg = excep.GetDescription();
385  ErrorMessage.Send(msg);
386 
387  return;
388  }
389  m_ProgressCommand->SetProgress(progress_steps);
390  CurrentlyBusy.Send(false);
391 
392  // make output visible
394  CastToMitkImage(m_ThresholdFilter->GetOutput(), result);
395  result->GetGeometry()->SetOrigin(m_ReferenceImage->GetGeometry()->GetOrigin());
396  result->GetGeometry()->SetIndexToWorldTransform(m_ReferenceImage->GetGeometry()->GetIndexToWorldTransform());
397  m_ResultImageNode->SetData(result);
398  m_ResultImageNode->SetVisibility(true);
400 
401  // add interaction with poinset again
402  m_SeedPointInteractor->SetDataNode(m_SeedsAsPointSetNode);
403  }
404 }
405 
407 {
408  // clear seeds for FastMarching as well as the PointSet for visualization
409  if (this->m_SeedContainer.IsNotNull())
410  this->m_SeedContainer->Initialize();
411 
412  if (this->m_SeedsAsPointSet.IsNotNull())
413  {
414  // remove observers from current pointset
415  m_SeedsAsPointSet->RemoveObserver(m_PointSetAddObserverTag);
416  m_SeedsAsPointSet->RemoveObserver(m_PointSetRemoveObserverTag);
417 
418  // renew pointset
419  this->m_SeedsAsPointSet = mitk::PointSet::New();
420  this->m_SeedsAsPointSetNode->SetData(this->m_SeedsAsPointSet);
421  m_SeedsAsPointSetNode->SetName("Seeds_Preview");
422  m_SeedsAsPointSetNode->SetBoolProperty("helper object", true);
423  m_SeedsAsPointSetNode->SetColor(0.0, 1.0, 0.0);
424  m_SeedsAsPointSetNode->SetVisibility(true);
425 
426  // add callback function for adding and removing points
429  pointAddedCommand->SetCallbackFunction(this, &mitk::FastMarchingTool3D::OnAddPoint);
430  m_PointSetAddObserverTag = m_SeedsAsPointSet->AddObserver(mitk::PointSetAddEvent(), pointAddedCommand);
431 
434  pointRemovedCommand->SetCallbackFunction(this, &mitk::FastMarchingTool3D::OnDelete);
435  m_PointSetRemoveObserverTag = m_SeedsAsPointSet->AddObserver(mitk::PointSetRemoveEvent(), pointRemovedCommand);
436  }
437 
438  if (this->m_FastMarchingFilter.IsNotNull())
439  m_FastMarchingFilter->Modified();
440 
441  this->m_NeedUpdate = true;
442 }
443 
445 {
446  // clear all seeds and preview empty result
447  this->ClearSeeds();
448 
449  m_ResultImageNode->SetVisibility(false);
450 
452 }
453 
455 {
456  if (m_CurrentTimeStep != t)
457  {
458  m_CurrentTimeStep = t;
459 
460  this->Initialize();
461  }
462 }
itk::SmartPointer< Self > Pointer
void SetAlpha(double)
Set parameter used in Fast Marching filter.
virtual void OnAddPoint()
Add point action of StateMachine pattern.
Base of all data objects.
Definition: mitkBaseData.h:39
virtual const char * GetName() const override
Returns the name of this tool. Make it short!
bool CanHandle(BaseData *referenceData) const override
#define MITK_ERROR
Definition: mitkLogMacros.h:24
static Pointer New()
FastMarching semgentation tool.
void Update()
Updates the itk pipeline and shows the result of FastMarching.
static void Update(vtkPolyData *)
Definition: mitkSurface.cpp:35
#define MITKSEGMENTATION_EXPORT
DataCollection - Class to facilitate loading/accessing structured data.
#define MITK_TOOL_MACRO(EXPORT_SPEC, CLASS_NAME, DESCRIPTION)
void SetSigma(double)
Set parameter used in Gradient Magnitude filter.
Constants for most interaction classes, due to the generic StateMachines.
virtual void SetCurrentTimeStep(int t)
Set the working time step.
virtual const char ** GetXPM() const override
Returns an icon in the XPM format.
virtual void ConfirmSegmentation()
Adds the feedback image to the current working image.
static Pointer New()
virtual void OnDelete()
Delete action of StateMachine pattern.
void SetStoppingValue(double)
Set parameter used in Fast Marching filter.
void SetUpperThreshold(double)
Set parameter used in Threshold filter.
virtual void Deactivated() override
Called when the tool gets deactivated.
virtual void Activated() override
Called when the tool gets activated.
void SetLowerThreshold(double)
Set parameter used in Threshold filter.
static Pointer New()
static RenderingManager * GetInstance()
Module * GetModule() const
Image class for storing images.
Definition: mitkImage.h:76
Operation that handles all actions on one Point.
Superclass for tool that create a new segmentation without user interaction in render windows...
void SetBeta(double)
Set parameter used in Fast Marching filter.
FastMarchingFilterType::NodeType NodeType
static Pointer New()
us::ModuleResource GetIconResource() const override
Returns the tool button icon of the tool wrapped by a usModuleResource.
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.
unsigned int GetDimension() const
Get dimension of the image.
Definition: mitkImage.cpp:110
ModuleResource GetResource(const std::string &path) const
Definition: usModule.cpp:267
static ModuleContext * GetModuleContext()
Returns the module context of the calling module.
void RequestUpdateAll(RequestType type=REQUEST_UPDATE_ALL)
void ClearSeeds()
Clear all seed points.
void Reset()
Reset all relevant inputs of the itk pipeline.
static Pointer New()
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.