Medical Imaging Interaction Toolkit  2018.4.99-87d68d9f
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 (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 
13 #include "mitkFastMarchingTool3D.h"
14 #include "mitkToolManager.h"
15 
16 #include "mitkBaseRenderer.h"
17 #include "mitkInteractionConst.h"
18 #include "mitkRenderingManager.h"
19 
20 #include "itkOrImageFilter.h"
21 #include "mitkImageCast.h"
22 #include "mitkImageTimeSelector.h"
23 
24 // us
25 #include <usGetModuleContext.h>
26 #include <usModule.h>
27 #include <usModuleContext.h>
28 #include <usModuleResource.h>
29 
30 namespace mitk
31 {
33 }
34 
36  : /*FeedbackContourTool*/ AutoSegmentationTool(),
37  m_NeedUpdate(true),
38  m_CurrentTimeStep(0),
39  m_LowerThreshold(0),
40  m_UpperThreshold(200),
41  m_StoppingValue(100),
42  m_Sigma(1.0),
43  m_Alpha(-0.5),
44  m_Beta(3.0),
45  m_PointSetAddObserverTag(0),
46  m_PointSetRemoveObserverTag(0)
47 {
48 }
49 
51 {
52 }
53 
55 {
56  if (referenceData == nullptr)
57  return false;
58 
59  auto *image = dynamic_cast<Image *>(referenceData);
60 
61  if (image == nullptr)
62  return false;
63 
64  if (image->GetDimension() < 3)
65  return false;
66 
67  return true;
68 }
69 
71 {
72  return nullptr; // mitkFastMarchingTool3D_xpm;
73 }
74 
76 {
78  us::ModuleResource resource = module->GetResource("FastMarching_48x48.png");
79  return resource;
80 }
81 
83 {
84  return "Fast Marching 3D";
85 }
86 
88 {
89  m_UpperThreshold = value / 10.0;
90  m_ThresholdFilter->SetUpperThreshold(m_UpperThreshold);
91  m_NeedUpdate = true;
92 }
93 
95 {
96  m_LowerThreshold = value / 10.0;
97  m_ThresholdFilter->SetLowerThreshold(m_LowerThreshold);
98  m_NeedUpdate = true;
99 }
100 
102 {
103  if (m_Beta != value)
104  {
105  m_Beta = value;
106  m_SigmoidFilter->SetBeta(m_Beta);
107  m_NeedUpdate = true;
108  }
109 }
110 
112 {
113  if (m_Sigma != value)
114  {
115  if (value > 0.0)
116  {
117  m_Sigma = value;
119  m_NeedUpdate = true;
120  }
121  }
122 }
123 
125 {
126  if (m_Alpha != value)
127  {
128  m_Alpha = value;
129  m_SigmoidFilter->SetAlpha(m_Alpha);
130  m_NeedUpdate = true;
131  }
132 }
133 
135 {
136  if (m_StoppingValue != value)
137  {
138  m_StoppingValue = value;
139  m_FastMarchingFilter->SetStoppingValue(m_StoppingValue);
140  m_NeedUpdate = true;
141  }
142 }
143 
145 {
146  Superclass::Activated();
147 
149  m_ResultImageNode->SetName("FastMarching_Preview");
150  m_ResultImageNode->SetBoolProperty("helper object", true);
151  m_ResultImageNode->SetColor(0.0, 1.0, 0.0);
152  m_ResultImageNode->SetVisibility(true);
154 
158  m_SeedsAsPointSetNode->SetName("3D_FastMarching_PointSet");
159  m_SeedsAsPointSetNode->SetBoolProperty("helper object", true);
160  m_SeedsAsPointSetNode->SetColor(0.0, 1.0, 0.0);
161  m_SeedsAsPointSetNode->SetVisibility(true);
162 
163  // Create PointSetData Interactor
165  // Load the according state machine for regular point set interaction
166  m_SeedPointInteractor->LoadStateMachine("PointSet.xml");
167  // Set the configuration file that defines the triggers for the transitions
168  m_SeedPointInteractor->SetEventConfig("PointSetConfig.xml");
169  // set the DataNode (which already is added to the DataStorage
171 
172  m_ReferenceImageAsITK = InternalImageType::New();
173 
175 
176  m_ThresholdFilter = ThresholdingFilterType::New();
177  m_ThresholdFilter->SetLowerThreshold(m_LowerThreshold);
178  m_ThresholdFilter->SetUpperThreshold(m_UpperThreshold);
179  m_ThresholdFilter->SetOutsideValue(0);
180  m_ThresholdFilter->SetInsideValue(1.0);
181 
182  m_SmoothFilter = SmoothingFilterType::New();
183  m_SmoothFilter->AddObserver(itk::ProgressEvent(), m_ProgressCommand);
184  m_SmoothFilter->SetTimeStep(0.05);
185  m_SmoothFilter->SetNumberOfIterations(2);
186  m_SmoothFilter->SetConductanceParameter(9.0);
187 
188  m_GradientMagnitudeFilter = GradientFilterType::New();
189  m_GradientMagnitudeFilter->AddObserver(itk::ProgressEvent(), m_ProgressCommand);
191 
192  m_SigmoidFilter = SigmoidFilterType::New();
193  m_SigmoidFilter->AddObserver(itk::ProgressEvent(), m_ProgressCommand);
194  m_SigmoidFilter->SetAlpha(m_Alpha);
195  m_SigmoidFilter->SetBeta(m_Beta);
196  m_SigmoidFilter->SetOutputMinimum(0.0);
197  m_SigmoidFilter->SetOutputMaximum(1.0);
198 
199  m_FastMarchingFilter = FastMarchingFilterType::New();
200  m_FastMarchingFilter->AddObserver(itk::ProgressEvent(), m_ProgressCommand);
201  m_FastMarchingFilter->SetStoppingValue(m_StoppingValue);
202 
203  m_SeedContainer = NodeContainer::New();
204  m_SeedContainer->Initialize();
205  m_FastMarchingFilter->SetTrialPoints(m_SeedContainer);
206 
207  // set up pipeline
209  m_GradientMagnitudeFilter->SetInput(m_SmoothFilter->GetOutput());
210  m_SigmoidFilter->SetInput(m_GradientMagnitudeFilter->GetOutput());
211  m_FastMarchingFilter->SetInput(m_SigmoidFilter->GetOutput());
212  m_ThresholdFilter->SetInput(m_FastMarchingFilter->GetOutput());
213 
215 
216  itk::SimpleMemberCommand<mitk::FastMarchingTool3D>::Pointer pointAddedCommand =
217  itk::SimpleMemberCommand<mitk::FastMarchingTool3D>::New();
218  pointAddedCommand->SetCallbackFunction(this, &mitk::FastMarchingTool3D::OnAddPoint);
219  m_PointSetAddObserverTag = m_SeedsAsPointSet->AddObserver(mitk::PointSetAddEvent(), pointAddedCommand);
220 
221  itk::SimpleMemberCommand<mitk::FastMarchingTool3D>::Pointer pointRemovedCommand =
222  itk::SimpleMemberCommand<mitk::FastMarchingTool3D>::New();
223  pointRemovedCommand->SetCallbackFunction(this, &mitk::FastMarchingTool3D::OnDelete);
224  m_PointSetRemoveObserverTag = m_SeedsAsPointSet->AddObserver(mitk::PointSetRemoveEvent(), pointRemovedCommand);
225 
226  this->Initialize();
227 }
228 
230 {
233  this->ClearSeeds();
234  this->m_SmoothFilter->RemoveAllObservers();
235  this->m_SigmoidFilter->RemoveAllObservers();
236  this->m_GradientMagnitudeFilter->RemoveAllObservers();
237  this->m_FastMarchingFilter->RemoveAllObservers();
238  m_ResultImageNode = nullptr;
240 
241  unsigned int numberOfPoints = m_SeedsAsPointSet->GetSize();
242  for (unsigned int i = 0; i < numberOfPoints; ++i)
243  {
244  mitk::Point3D point = m_SeedsAsPointSet->GetPoint(i);
245  auto *doOp = new mitk::PointOperation(mitk::OpREMOVE, point, 0);
246  m_SeedsAsPointSet->ExecuteOperation(doOp);
247  }
248  // Deactivate Interaction
249  m_SeedPointInteractor->SetDataNode(nullptr);
251  m_SeedsAsPointSetNode = nullptr;
254 
255  Superclass::Deactivated();
256 }
257 
259 {
260  m_ReferenceImage = dynamic_cast<mitk::Image *>(m_ToolManager->GetReferenceData(0)->GetData());
261  if (m_ReferenceImage->GetTimeGeometry()->CountTimeSteps() > 1)
262  {
264  timeSelector->SetInput(m_ReferenceImage);
265  timeSelector->SetTimeNr(m_CurrentTimeStep);
266  timeSelector->UpdateLargestPossibleRegion();
267  m_ReferenceImage = timeSelector->GetOutput();
268  }
271  m_NeedUpdate = true;
272 }
273 
275 {
276  // combine preview image with current working segmentation
277  if (dynamic_cast<mitk::Image *>(m_ResultImageNode->GetData()))
278  {
279  // logical or combination of preview and segmentation slice
280  OutputImageType::Pointer segmentationImageInITK = OutputImageType::New();
281 
282  mitk::Image::Pointer workingImage = dynamic_cast<mitk::Image *>(GetTargetSegmentationNode()->GetData());
283  if (workingImage->GetTimeGeometry()->CountTimeSteps() > 1)
284  {
286  timeSelector->SetInput(workingImage);
287  timeSelector->SetTimeNr(m_CurrentTimeStep);
288  timeSelector->UpdateLargestPossibleRegion();
289  CastToItkImage(timeSelector->GetOutput(), segmentationImageInITK);
290  }
291  else
292  {
293  CastToItkImage(workingImage, segmentationImageInITK);
294  }
295 
296  typedef itk::OrImageFilter<OutputImageType, OutputImageType> OrImageFilterType;
297  OrImageFilterType::Pointer orFilter = OrImageFilterType::New();
298 
299  orFilter->SetInput(0, m_ThresholdFilter->GetOutput());
300  orFilter->SetInput(1, segmentationImageInITK);
301  orFilter->Update();
302 
303  // set image volume in current time step from itk image
304  workingImage->SetVolume((void *)(m_ThresholdFilter->GetOutput()->GetPixelContainer()->GetBufferPointer()),
306  this->m_ResultImageNode->SetVisibility(false);
307  this->ClearSeeds();
308  workingImage->Modified();
309  }
310 
313 }
314 
316 {
317  // Add a new seed point for FastMarching algorithm
318  mitk::Point3D clickInIndex;
319 
320  m_ReferenceImage->GetGeometry()->WorldToIndex(m_SeedsAsPointSet->GetPoint(m_SeedsAsPointSet->GetSize() - 1),
321  clickInIndex);
322  itk::Index<3> seedPosition;
323  seedPosition[0] = clickInIndex[0];
324  seedPosition[1] = clickInIndex[1];
325  seedPosition[2] = clickInIndex[2];
326 
327  NodeType node;
328  const double seedValue = 0.0;
329  node.SetValue(seedValue);
330  node.SetIndex(seedPosition);
331  this->m_SeedContainer->InsertElement(this->m_SeedContainer->Size(), node);
332  m_FastMarchingFilter->Modified();
333 
335 
336  m_NeedUpdate = true;
337 
338  this->Update();
339 
340  m_ReadyMessage.Send();
341 }
342 
344 {
345  // delete last seed point
346  if (!(this->m_SeedContainer->empty()))
347  {
348  // delete last element of seeds container
349  this->m_SeedContainer->pop_back();
350  m_FastMarchingFilter->Modified();
351 
353 
354  m_NeedUpdate = true;
355 
356  this->Update();
357  }
358 }
359 
361 {
362  const unsigned int progress_steps = 200;
363 
364  if (m_NeedUpdate)
365  {
366  m_ProgressCommand->AddStepsToDo(progress_steps);
367 
368  // remove interaction with poinset while updating
369  m_SeedPointInteractor->SetDataNode(nullptr);
370  CurrentlyBusy.Send(true);
371  try
372  {
373  m_ThresholdFilter->Update();
374  }
375  catch (itk::ExceptionObject &excep)
376  {
377  MITK_ERROR << "Exception caught: " << excep.GetDescription();
378 
379  m_ProgressCommand->SetProgress(progress_steps);
380  CurrentlyBusy.Send(false);
381 
382  std::string msg = excep.GetDescription();
383  ErrorMessage.Send(msg);
384 
385  return;
386  }
387  m_ProgressCommand->SetProgress(progress_steps);
388  CurrentlyBusy.Send(false);
389 
390  // make output visible
392  CastToMitkImage(m_ThresholdFilter->GetOutput(), result);
393  result->GetGeometry()->SetOrigin(m_ReferenceImage->GetGeometry()->GetOrigin());
394  result->GetGeometry()->SetIndexToWorldTransform(m_ReferenceImage->GetGeometry()->GetIndexToWorldTransform());
395  m_ResultImageNode->SetData(result);
396  m_ResultImageNode->SetVisibility(true);
398 
399  // add interaction with poinset again
401  }
402 }
403 
405 {
406  // clear seeds for FastMarching as well as the PointSet for visualization
407  if (this->m_SeedContainer.IsNotNull())
408  this->m_SeedContainer->Initialize();
409 
410  if (this->m_SeedsAsPointSet.IsNotNull())
411  {
412  // remove observers from current pointset
415 
416  // renew pointset
418  this->m_SeedsAsPointSetNode->SetData(this->m_SeedsAsPointSet);
419  m_SeedsAsPointSetNode->SetName("Seeds_Preview");
420  m_SeedsAsPointSetNode->SetBoolProperty("helper object", true);
421  m_SeedsAsPointSetNode->SetColor(0.0, 1.0, 0.0);
422  m_SeedsAsPointSetNode->SetVisibility(true);
423 
424  // add callback function for adding and removing points
425  itk::SimpleMemberCommand<mitk::FastMarchingTool3D>::Pointer pointAddedCommand =
426  itk::SimpleMemberCommand<mitk::FastMarchingTool3D>::New();
427  pointAddedCommand->SetCallbackFunction(this, &mitk::FastMarchingTool3D::OnAddPoint);
428  m_PointSetAddObserverTag = m_SeedsAsPointSet->AddObserver(mitk::PointSetAddEvent(), pointAddedCommand);
429 
430  itk::SimpleMemberCommand<mitk::FastMarchingTool3D>::Pointer pointRemovedCommand =
431  itk::SimpleMemberCommand<mitk::FastMarchingTool3D>::New();
432  pointRemovedCommand->SetCallbackFunction(this, &mitk::FastMarchingTool3D::OnDelete);
433  m_PointSetRemoveObserverTag = m_SeedsAsPointSet->AddObserver(mitk::PointSetRemoveEvent(), pointRemovedCommand);
434  }
435 
436  if (this->m_FastMarchingFilter.IsNotNull())
437  m_FastMarchingFilter->Modified();
438 
439  this->m_NeedUpdate = true;
440 }
441 
443 {
444  // clear all seeds and preview empty result
445  this->ClearSeeds();
446 
447  m_ResultImageNode->SetVisibility(false);
448 
450 }
451 
453 {
454  if (m_CurrentTimeStep != t)
455  {
456  m_CurrentTimeStep = t;
457 
458  this->Initialize();
459  }
460 }
void SetAlpha(double)
Set parameter used in Fast Marching filter.
SigmoidFilterType::Pointer m_SigmoidFilter
SmoothingFilterType::Pointer m_SmoothFilter
DataStorage * GetDataStorage()
virtual void OnAddPoint()
Add point action of StateMachine pattern.
Base of all data objects.
Definition: mitkBaseData.h:37
Message1< bool > CurrentlyBusy
To send whether the tool is busy (to be shown by some GUI)
Definition: mitkTool.h:104
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:20
InternalImageType::Pointer m_ReferenceImageAsITK
static Pointer New()
mitk::ToolCommand::Pointer m_ProgressCommand
FastMarching semgentation tool.
void Send(T t)
Definition: mitkMessage.h:602
void Update()
Updates the itk pipeline and shows the result of FastMarching.
#define MITKSEGMENTATION_EXPORT
DataCollection - Class to facilitate loading/accessing structured data.
mitk::DataNode::Pointer m_SeedsAsPointSetNode
Message1< std::string > ErrorMessage
To send error messages (to be shown by some GUI)
Definition: mitkTool.h:99
void SetSigma(double)
Set parameter used in Gradient Magnitude filter.
Constants for most interaction classes, due to the generic StateMachines.
virtual void Add(DataNode *node, const DataStorage::SetOfObjects *parents=nullptr)=0
Adds a DataNode containing a data object to its internal storage.
virtual void SetCurrentTimeStep(int t)
Set the working time step.
const char ** GetXPM() const override
Returns an icon in the XPM format.
bool ActivateTool(int id)
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.
mitk::PointSet::Pointer m_SeedsAsPointSet
mitk::DataNode::Pointer m_ResultImageNode
void SetUpperThreshold(double)
Set parameter used in Threshold filter.
MITK_TOOL_MACRO(MITKSEGMENTATION_EXPORT, LiveWireTool2D, "LiveWire tool")
void Deactivated() override
Called when the tool gets deactivated.
BaseData * GetData() const
Get the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
void Activated() override
Called when the tool gets activated.
GradientFilterType::Pointer m_GradientMagnitudeFilter
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:72
ModuleResource GetResource(const std::string &path) const
Definition: usModule.cpp:267
Operation that handles all actions on one Point.
Superclass for tool that create a new segmentation without user interaction in render windows...
virtual mitk::DataNode * GetTargetSegmentationNode()
Depending on the selected mode either returns the currently selected segmentation or creates a new on...
void SetBeta(double)
Set parameter used in Fast Marching filter.
FastMarchingFilterType::NodeType NodeType
mitk::Image::Pointer image
static Pointer New()
us::ModuleResource GetIconResource() const override
Returns the tool button icon of the tool wrapped by a usModuleResource.
mitk::PointSetDataInteractor::Pointer m_SeedPointInteractor
virtual void Remove(const DataNode *node)=0
Removes node from the DataStorage.
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:74
void MITKCORE_EXPORT CastToItkImage(const mitk::Image *mitkImage, itk::SmartPointer< ItkOutputImageType > &itkOutputImage)
Cast an mitk::Image to an itk::Image with a specific type.
NodeContainer::Pointer m_SeedContainer
DataVectorType GetReferenceData()
ToolManager * m_ToolManager
Definition: mitkTool.h:228
FastMarchingFilterType::Pointer m_FastMarchingFilter
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()
ThresholdingFilterType::Pointer m_ThresholdFilter
DataVectorType GetWorkingData()