Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkLiveWireTool2D.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 <itkGradientMagnitudeImageFilter.h>
18 
19 #include <mitkBaseRenderer.h>
20 #include <mitkContour.h>
21 #include <mitkContourModelUtils.h>
22 #include <mitkContourUtils.h>
23 #include <mitkInteractionConst.h>
24 #include <mitkRenderingManager.h>
25 #include <mitkToolManager.h>
26 
27 #include <usGetModuleContext.h>
28 #include <usModule.h>
29 #include <usModuleContext.h>
30 #include <usModuleResource.h>
31 
32 #include "mitkLiveWireTool2D.h"
33 #include "mitkLiveWireTool2D.xpm"
34 
35 namespace mitk
36 {
38 }
39 
40 class RemoveFromDataStorage
41 {
42 public:
43  RemoveFromDataStorage(mitk::DataStorage::Pointer dataStorage) : m_DataStorage(dataStorage) {}
44  void operator()(mitk::DataNode *dataNode) { m_DataStorage->Remove(dataNode); }
45  void operator()(const std::pair<mitk::DataNode::Pointer, mitk::PlaneGeometry::Pointer> &dataNode)
46  {
47  m_DataStorage->Remove(dataNode.first);
48  }
49 
50 private:
52 };
53 
54 mitk::LiveWireTool2D::LiveWireTool2D() : SegTool2D("LiveWireTool"), m_PlaneGeometry(NULL)
55 {
56 }
57 
59 {
60  this->ClearSegmentation();
61 }
62 
63 void mitk::LiveWireTool2D::RemoveHelperObjects()
64 {
65  DataStorage *dataStorage = m_ToolManager->GetDataStorage();
66 
67  if (!m_EditingContours.empty())
68  std::for_each(m_EditingContours.begin(), m_EditingContours.end(), RemoveFromDataStorage(dataStorage));
69 
70  if (!m_WorkingContours.empty())
71  std::for_each(m_WorkingContours.begin(), m_WorkingContours.end(), RemoveFromDataStorage(dataStorage));
72 
73  if (m_EditingContourNode.IsNotNull())
74  dataStorage->Remove(m_EditingContourNode);
75 
76  if (m_LiveWireContourNode.IsNotNull())
77  dataStorage->Remove(m_LiveWireContourNode);
78 
79  if (m_ContourModelNode.IsNotNull())
80  dataStorage->Remove(m_ContourModelNode);
81 
83 }
84 
85 void mitk::LiveWireTool2D::ReleaseHelperObjects()
86 {
87  this->RemoveHelperObjects();
88 
89  if (!m_EditingContours.empty())
90  m_EditingContours.clear();
91 
92  if (!m_WorkingContours.empty())
93  m_WorkingContours.clear();
94 
95  m_EditingContourNode = NULL;
96  m_EditingContour = NULL;
97 
98  m_LiveWireContourNode = NULL;
99  m_LiveWireContour = NULL;
100 
101  m_ContourModelNode = NULL;
102  m_Contour = NULL;
103 }
104 
105 void mitk::LiveWireTool2D::ReleaseInteractors()
106 {
107  this->EnableContourLiveWireInteraction(false);
108  m_LiveWireNodes.clear();
109 }
110 
112 {
113  CONNECT_CONDITION("CheckContourClosed", OnCheckPoint);
114 
115  CONNECT_FUNCTION("InitObject", OnInitLiveWire);
116  CONNECT_FUNCTION("AddPoint", OnAddPoint);
117  CONNECT_FUNCTION("CtrlAddPoint", OnAddPoint);
118  CONNECT_FUNCTION("MovePoint", OnMouseMoveNoDynamicCosts);
119  CONNECT_FUNCTION("FinishContour", OnFinish);
120  CONNECT_FUNCTION("DeletePoint", OnLastSegmentDelete);
121  CONNECT_FUNCTION("CtrlMovePoint", OnMouseMoved);
122 }
123 
124 const char **mitk::LiveWireTool2D::GetXPM() const
125 {
126  return mitkLiveWireTool2D_xpm;
127 }
128 
130 {
131  return us::GetModuleContext()->GetModule()->GetResource("LiveWire_48x48.png");
132 }
133 
135 {
136  return us::GetModuleContext()->GetModule()->GetResource("LiveWire_Cursor_32x32.png");
137 }
138 
139 const char *mitk::LiveWireTool2D::GetName() const
140 {
141  return "Live Wire";
142 }
143 
145 {
146  Superclass::Activated();
147  this->ResetToStartState();
148  this->EnableContourLiveWireInteraction(true);
149 }
150 
152 {
153  this->ConfirmSegmentation();
154  Superclass::Deactivated();
155 }
156 
158 {
159  for (auto interactor : m_LiveWireNodes)
160  {
161  if (on)
162  interactor->EnableInteraction(true);
163  else
164  interactor->EnableInteraction(false);
165  }
166 }
167 
169 {
170  DataNode *workingNode(m_ToolManager->GetWorkingData(0));
171 
172  if (!workingNode)
173  return;
174 
175  Image *workingImage = dynamic_cast<Image *>(workingNode->GetData());
176 
177  if (!workingImage)
178  return;
179 
180  // for all contours in list (currently created by tool)
181  std::vector<std::pair<mitk::DataNode::Pointer, mitk::PlaneGeometry::Pointer>>::iterator itWorkingContours =
182  this->m_WorkingContours.begin();
183  std::vector<SliceInformation> sliceList;
184  sliceList.reserve(m_WorkingContours.size());
185  while (itWorkingContours != this->m_WorkingContours.end())
186  {
187  // if node contains data
188  if (itWorkingContours->first->GetData())
189  {
190  // if this is a contourModel
191  mitk::ContourModel *contourModel = dynamic_cast<mitk::ContourModel *>(itWorkingContours->first->GetData());
192  if (contourModel)
193  {
194  // for each timestep of this contourModel
195  for (TimeStepType currentTimestep = 0; currentTimestep < contourModel->GetTimeGeometry()->CountTimeSteps();
196  ++currentTimestep)
197  {
198  // get the segmentation image slice at current timestep
199  mitk::Image::Pointer workingSlice =
200  this->GetAffectedImageSliceAs2DImage(itWorkingContours->second, workingImage, currentTimestep);
201 
202  mitk::ContourModel::Pointer projectedContour =
203  mitk::ContourModelUtils::ProjectContourTo2DSlice(workingSlice, contourModel, true, false);
204  mitk::ContourModelUtils::FillContourInSlice(projectedContour, workingSlice, workingImage, 1.0);
205 
206  // write back to image volume
207  SliceInformation sliceInfo(workingSlice, itWorkingContours->second, currentTimestep);
208  sliceList.push_back(sliceInfo);
209  this->WriteSliceToVolume(sliceInfo);
210  }
211  }
212  }
213  ++itWorkingContours;
214  }
215 
216  this->WriteBackSegmentationResult(sliceList, false);
217  this->ClearSegmentation();
218 }
219 
221 {
222  this->ReleaseHelperObjects();
223  this->ReleaseInteractors();
224  this->ResetToStartState();
225 }
226 
228  mitk::BaseData *data)
229 {
230  bool IsPositionEventInsideImageRegion =
231  data != nullptr && data->GetGeometry()->IsInside(positionEvent->GetPositionInWorld());
232  if (!IsPositionEventInsideImageRegion)
233  {
234  MITK_WARN("LiveWireTool2D") << "PositionEvent is outside ImageRegion!";
235  return false;
236  }
237  return true;
238 }
239 
241 {
242  mitk::InteractionPositionEvent *positionEvent = dynamic_cast<mitk::InteractionPositionEvent *>(interactionEvent);
243 
244  if (!positionEvent)
245  return;
246 
247  mitk::DataNode *workingDataNode = m_ToolManager->GetWorkingData(0);
248  if (!IsPositionEventInsideImageRegion(positionEvent, workingDataNode->GetData()))
249  {
250  this->ResetToStartState();
251  return;
252  }
253 
254  m_LastEventSender = positionEvent->GetSender();
255  m_LastEventSlice = m_LastEventSender->GetSlice();
256 
257  int timestep = positionEvent->GetSender()->GetTimeStep();
258 
259  m_Contour = mitk::ContourModel::New();
260  m_Contour->Expand(timestep + 1);
261  m_ContourModelNode = mitk::DataNode::New();
262  m_ContourModelNode->SetData(m_Contour);
263  m_ContourModelNode->SetName("working contour node");
264  m_ContourModelNode->SetProperty("layer", IntProperty::New(100));
265  m_ContourModelNode->AddProperty("fixedLayer", BoolProperty::New(true));
266  m_ContourModelNode->SetProperty("helper object", mitk::BoolProperty::New(true));
267  m_ContourModelNode->AddProperty("contour.color", ColorProperty::New(1, 1, 0), NULL, true);
268  m_ContourModelNode->AddProperty("contour.points.color", ColorProperty::New(1.0, 0.0, 0.1), NULL, true);
269  m_ContourModelNode->AddProperty("contour.controlpoints.show", BoolProperty::New(true), NULL, true);
270 
271  m_LiveWireContour = mitk::ContourModel::New();
272  m_LiveWireContour->Expand(timestep + 1);
273  m_LiveWireContourNode = mitk::DataNode::New();
274  m_LiveWireContourNode->SetData(m_LiveWireContour);
275  m_LiveWireContourNode->SetName("active livewire node");
276  m_LiveWireContourNode->SetProperty("layer", IntProperty::New(101));
277  m_LiveWireContourNode->AddProperty("fixedLayer", BoolProperty::New(true));
278  m_LiveWireContourNode->SetProperty("helper object", mitk::BoolProperty::New(true));
279  m_LiveWireContourNode->AddProperty("contour.color", ColorProperty::New(0.1, 1.0, 0.1), NULL, true);
280  m_LiveWireContourNode->AddProperty("contour.width", mitk::FloatProperty::New(4.0), NULL, true);
281 
282  m_EditingContour = mitk::ContourModel::New();
283  m_EditingContour->Expand(timestep + 1);
284  m_EditingContourNode = mitk::DataNode::New();
285  m_EditingContourNode->SetData(m_EditingContour);
286  m_EditingContourNode->SetName("editing node");
287  m_EditingContourNode->SetProperty("layer", IntProperty::New(102));
288  m_EditingContourNode->AddProperty("fixedLayer", BoolProperty::New(true));
289  m_EditingContourNode->SetProperty("helper object", mitk::BoolProperty::New(true));
290  m_EditingContourNode->AddProperty("contour.color", ColorProperty::New(0.1, 1.0, 0.1), NULL, true);
291  m_EditingContourNode->AddProperty("contour.points.color", ColorProperty::New(0.0, 0.0, 1.0), NULL, true);
292  m_EditingContourNode->AddProperty("contour.width", mitk::FloatProperty::New(4.0), NULL, true);
293 
294  m_ToolManager->GetDataStorage()->Add(m_ContourModelNode, workingDataNode);
295  m_ToolManager->GetDataStorage()->Add(m_LiveWireContourNode, workingDataNode);
296  m_ToolManager->GetDataStorage()->Add(m_EditingContourNode, workingDataNode);
297 
298  // set current slice as input for ImageToLiveWireContourFilter
299  m_WorkingSlice = this->GetAffectedReferenceSlice(positionEvent);
300 
301  mitk::Point3D newOrigin = m_WorkingSlice->GetSlicedGeometry()->GetOrigin();
302  m_WorkingSlice->GetSlicedGeometry()->WorldToIndex(newOrigin, newOrigin);
303  m_WorkingSlice->GetSlicedGeometry()->IndexToWorld(newOrigin, newOrigin);
304  m_WorkingSlice->GetSlicedGeometry()->SetOrigin(newOrigin);
305 
306  m_LiveWireFilter = mitk::ImageLiveWireContourModelFilter::New();
307  m_LiveWireFilter->SetInput(m_WorkingSlice);
308 
309  // map click to pixel coordinates
310  mitk::Point3D click = positionEvent->GetPositionInWorld();
311  itk::Index<3> idx;
312  m_WorkingSlice->GetGeometry()->WorldToIndex(click, idx);
313 
314  // get the pixel the gradient in region of 5x5
315  itk::Index<3> indexWithHighestGradient;
316  AccessFixedDimensionByItk_2(m_WorkingSlice, FindHighestGradientMagnitudeByITK, 2, idx, indexWithHighestGradient);
317 
318  // itk::Index to mitk::Point3D
319  click[0] = indexWithHighestGradient[0];
320  click[1] = indexWithHighestGradient[1];
321  click[2] = indexWithHighestGradient[2];
322  m_WorkingSlice->GetGeometry()->IndexToWorld(click, click);
323 
324  // set initial start point
325  m_Contour->AddVertex(click, true, timestep);
326  m_LiveWireFilter->SetStartPoint(click);
327  // remember plane geometry to determine if events were triggered in same plane
328  m_PlaneGeometry = interactionEvent->GetSender()->GetCurrentWorldPlaneGeometry();
329 
330  m_CreateAndUseDynamicCosts = true;
331 
332  // render
333  assert(positionEvent->GetSender()->GetRenderWindow());
335 }
336 
338 {
339  // complete LiveWire interaction for last segment
340  // add current LiveWire contour to the finished contour and reset
341  // to start new segment and computation
342 
343  mitk::InteractionPositionEvent *positionEvent = dynamic_cast<mitk::InteractionPositionEvent *>(interactionEvent);
344  if (!positionEvent)
345  return;
346 
347  if (m_PlaneGeometry != NULL)
348  {
349  // this checks that the point is in the correct slice
350  if (m_PlaneGeometry->DistanceFromPlane(positionEvent->GetPositionInWorld()) > mitk::sqrteps)
351  {
352  return;
353  }
354  }
355 
356  int timestep = positionEvent->GetSender()->GetTimeStep();
357 
358  // add repulsive points to avoid to get the same path again
359  typedef mitk::ImageLiveWireContourModelFilter::InternalImageType::IndexType IndexType;
360  mitk::ContourModel::ConstVertexIterator iter = m_LiveWireContour->IteratorBegin(timestep);
361  for (; iter != m_LiveWireContour->IteratorEnd(timestep); iter++)
362  {
363  IndexType idx;
364  this->m_WorkingSlice->GetGeometry()->WorldToIndex((*iter)->Coordinates, idx);
365 
366  this->m_LiveWireFilter->AddRepulsivePoint(idx);
367  }
368 
369  // remove duplicate first vertex, it's already contained in m_Contour
370  m_LiveWireContour->RemoveVertexAt(0, timestep);
371 
372  // set last added point as control point
373  m_LiveWireContour->SetControlVertexAt(m_LiveWireContour->GetNumberOfVertices(timestep) - 1, timestep);
374 
375  // merge contours
376  m_Contour->Concatenate(m_LiveWireContour, timestep);
377 
378  // clear the livewire contour and reset the corresponding datanode
379  m_LiveWireContour->Clear(timestep);
380 
381  // set new start point
382  m_LiveWireFilter->SetStartPoint(positionEvent->GetPositionInWorld());
383 
384  if (m_CreateAndUseDynamicCosts)
385  {
386  // use dynamic cost map for next update
387  m_LiveWireFilter->CreateDynamicCostMap(m_Contour);
388  m_LiveWireFilter->SetUseDynamicCostMap(true);
389  // m_CreateAndUseDynamicCosts = false;
390  }
391  // render
392  assert(positionEvent->GetSender()->GetRenderWindow());
394 }
395 
397 {
398  // compute LiveWire segment from last control point to current mouse position
399  mitk::InteractionPositionEvent *positionEvent = dynamic_cast<mitk::InteractionPositionEvent *>(interactionEvent);
400  if (!positionEvent)
401  return;
402 
403  // actual LiveWire computation
404  int timestep = positionEvent->GetSender()->GetTimeStep();
405 
406  m_LiveWireFilter->SetEndPoint(positionEvent->GetPositionInWorld());
407 
408  m_LiveWireFilter->SetTimeStep(timestep);
409  m_LiveWireFilter->Update();
410 
411  m_LiveWireContour = this->m_LiveWireFilter->GetOutput();
412  m_LiveWireContourNode->SetData(this->m_LiveWireContour);
413 
414  // render
415  assert(positionEvent->GetSender()->GetRenderWindow());
416  positionEvent->GetSender()->GetRenderingManager()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow());
417 }
418 
420 {
421  // do not use dynamic cost map
422  m_LiveWireFilter->SetUseDynamicCostMap(false);
423  OnMouseMoved(NULL, interactionEvent);
424  m_LiveWireFilter->SetUseDynamicCostMap(true);
425 }
426 
428 {
429  // check double click on first control point to finish the LiveWire tool
430  //
431  // Check distance to first point.
432  // Transition YES if click close to first control point
433  //
434 
435  const mitk::InteractionPositionEvent *positionEvent =
436  dynamic_cast<const mitk::InteractionPositionEvent *>(interactionEvent);
437  if (positionEvent)
438  {
439  int timestep = positionEvent->GetSender()->GetTimeStep();
440 
441  mitk::Point3D click = positionEvent->GetPositionInWorld();
442  mitk::Point3D first = this->m_Contour->GetVertexAt(0, timestep)->Coordinates;
443 
444  if (first.EuclideanDistanceTo(click) < 4.5)
445  {
446  // allow to finish
447  return true;
448  }
449  else
450  {
451  return false;
452  }
453  }
454 
455  return false;
456 }
457 
459 {
460  // finish livewire tool interaction
461 
462  mitk::InteractionPositionEvent *positionEvent = dynamic_cast<mitk::InteractionPositionEvent *>(interactionEvent);
463  if (!positionEvent)
464  return;
465 
466  // Have to do that here so that the m_LastEventSender is set correctly
468 
469  // actual timestep
470  int timestep = positionEvent->GetSender()->GetTimeStep();
471 
472  // remove last control point being added by double click
473  m_Contour->RemoveVertexAt(m_Contour->GetNumberOfVertices(timestep) - 1, timestep);
474 
475  // save contour and corresponding plane geometry to list
476  std::pair<mitk::DataNode::Pointer, mitk::PlaneGeometry::Pointer> cp(
477  m_ContourModelNode, (positionEvent->GetSender()->GetCurrentWorldPlaneGeometry()->Clone().GetPointer()));
478  this->m_WorkingContours.push_back(cp);
479 
480  std::pair<mitk::DataNode::Pointer, mitk::PlaneGeometry::Pointer> ecp(
481  m_EditingContourNode, (positionEvent->GetSender()->GetCurrentWorldPlaneGeometry()->Clone().GetPointer()));
482  this->m_EditingContours.push_back(ecp);
483 
484  m_LiveWireFilter->SetUseDynamicCostMap(false);
485 
486  this->FinishTool();
487 }
488 
490 {
491  int numberOfTimesteps = static_cast<int>(m_Contour->GetTimeGeometry()->CountTimeSteps());
492 
493  // close contour in each timestep
494  for (unsigned int i = 0; i <= numberOfTimesteps; i++)
495  {
496  m_Contour->Close(i);
497  }
498 
499  m_ToolManager->GetDataStorage()->Remove(m_LiveWireContourNode);
500 
501  // clear live wire contour node
502  m_LiveWireContourNode = NULL;
503  m_LiveWireContour = NULL;
504 
505  // A new ContourModelLiveWireInteractor is created that will listen to new events
506  // set the livewire interactor to edit control points
507  m_ContourInteractor = mitk::ContourModelLiveWireInteractor::New();
508  m_ContourInteractor->SetDataNode(m_ContourModelNode);
509  // TODO load statemachine and config
510  m_ContourInteractor->LoadStateMachine("ContourModelModificationInteractor.xml", us::GetModuleContext()->GetModule());
511  // Set the configuration file that defines the triggers for the transitions
512  m_ContourInteractor->SetEventConfig("ContourModelModificationConfig.xml", us::GetModuleContext()->GetModule());
513 
514  m_ContourInteractor->SetWorkingImage(this->m_WorkingSlice);
515  m_ContourInteractor->SetEditingContourModelNode(this->m_EditingContourNode);
516  m_ContourModelNode->SetDataInteractor(m_ContourInteractor.GetPointer());
517 
518  this->m_LiveWireNodes.push_back(m_ContourInteractor);
519 }
520 
522 {
523  int timestep = interactionEvent->GetSender()->GetTimeStep();
524 
525  // if last point of current contour will be removed go to start state and remove nodes
526  if (m_Contour->GetNumberOfVertices(timestep) <= 1)
527  {
528  m_ToolManager->GetDataStorage()->Remove(m_LiveWireContourNode);
529  m_ToolManager->GetDataStorage()->Remove(m_ContourModelNode);
530  m_ToolManager->GetDataStorage()->Remove(m_EditingContourNode);
531  m_LiveWireContour = mitk::ContourModel::New();
532  m_Contour = mitk::ContourModel::New();
533  m_ContourModelNode->SetData(m_Contour);
534  m_LiveWireContourNode->SetData(m_LiveWireContour);
535  this->ResetToStartState(); // go to start state
536  }
537  else // remove last segment from contour and reset livewire contour
538  {
539  m_LiveWireContour = mitk::ContourModel::New();
540 
541  m_LiveWireContourNode->SetData(m_LiveWireContour);
542 
544  newContour->Expand(m_Contour->GetTimeSteps());
545 
546  mitk::ContourModel::VertexIterator begin = m_Contour->IteratorBegin();
547 
548  // iterate from last point to next active point
549  mitk::ContourModel::VertexIterator newLast = m_Contour->IteratorBegin() + (m_Contour->GetNumberOfVertices() - 1);
550 
551  // go at least one down
552  if (newLast != begin)
553  {
554  newLast--;
555  }
556 
557  // search next active control point
558  while (newLast != begin && !((*newLast)->IsControlPoint))
559  {
560  newLast--;
561  }
562 
563  // set position of start point for livewire filter to coordinates of the new last point
564  m_LiveWireFilter->SetStartPoint((*newLast)->Coordinates);
565 
566  mitk::ContourModel::VertexIterator it = m_Contour->IteratorBegin();
567 
568  // fill new Contour
569  while (it <= newLast)
570  {
571  newContour->AddVertex((*it)->Coordinates, (*it)->IsControlPoint, timestep);
572  it++;
573  }
574 
575  newContour->SetClosed(m_Contour->IsClosed());
576 
577  // set new contour visible
578  m_ContourModelNode->SetData(newContour);
579 
580  m_Contour = newContour;
581 
582  assert(interactionEvent->GetSender()->GetRenderWindow());
584  }
585 }
586 
587 template <typename TPixel, unsigned int VImageDimension>
588 void mitk::LiveWireTool2D::FindHighestGradientMagnitudeByITK(itk::Image<TPixel, VImageDimension> *inputImage,
589  itk::Index<3> &index,
590  itk::Index<3> &returnIndex)
591 {
592  typedef itk::Image<TPixel, VImageDimension> InputImageType;
593  typedef typename InputImageType::IndexType IndexType;
594 
595  unsigned long xMAX = inputImage->GetLargestPossibleRegion().GetSize()[0];
596  unsigned long yMAX = inputImage->GetLargestPossibleRegion().GetSize()[1];
597 
598  returnIndex[0] = index[0];
599  returnIndex[1] = index[1];
600  returnIndex[2] = 0.0;
601 
602  double gradientMagnitude = 0.0;
603  double maxGradientMagnitude = 0.0;
604 
605  /*
606  the size and thus the region of 7x7 is only used to calculate the gradient magnitude in that region
607  not for searching the maximum value
608  */
609 
610  // maximum value in each direction for size
611  typename InputImageType::SizeType size;
612  size[0] = 7;
613  size[1] = 7;
614 
615  // minimum value in each direction for startRegion
616  IndexType startRegion;
617  startRegion[0] = index[0] - 3;
618  startRegion[1] = index[1] - 3;
619  if (startRegion[0] < 0)
620  startRegion[0] = 0;
621  if (startRegion[1] < 0)
622  startRegion[1] = 0;
623  if (xMAX - index[0] < 7)
624  startRegion[0] = xMAX - 7;
625  if (yMAX - index[1] < 7)
626  startRegion[1] = yMAX - 7;
627 
628  index[0] = startRegion[0] + 3;
629  index[1] = startRegion[1] + 3;
630 
631  typename InputImageType::RegionType region;
632  region.SetSize(size);
633  region.SetIndex(startRegion);
634 
635  typedef typename itk::GradientMagnitudeImageFilter<InputImageType, InputImageType> GradientMagnitudeFilterType;
637  gradientFilter->SetInput(inputImage);
638  gradientFilter->GetOutput()->SetRequestedRegion(region);
639 
640  gradientFilter->Update();
641  typename InputImageType::Pointer gradientMagnImage;
642  gradientMagnImage = gradientFilter->GetOutput();
643 
644  IndexType currentIndex;
645  currentIndex[0] = 0;
646  currentIndex[1] = 0;
647 
648  // search max (approximate) gradient magnitude
649  for (int x = -1; x <= 1; ++x)
650  {
651  currentIndex[0] = index[0] + x;
652 
653  for (int y = -1; y <= 1; ++y)
654  {
655  currentIndex[1] = index[1] + y;
656 
657  gradientMagnitude = gradientMagnImage->GetPixel(currentIndex);
658 
659  // check for new max
660  if (maxGradientMagnitude < gradientMagnitude)
661  {
662  maxGradientMagnitude = gradientMagnitude;
663  returnIndex[0] = currentIndex[0];
664  returnIndex[1] = currentIndex[1];
665  returnIndex[2] = 0.0;
666  } // end if
667  } // end for y
668 
669  currentIndex[1] = index[1];
670  } // end for x
671 }
virtual void Deactivated() override
Called when the tool gets deactivated.
ContourModel is a structure of linked vertices defining a contour in 3D space. The vertices are store...
Super class for all position events.
Data management class that handles 'was created by' relations.
itk::SmartPointer< Self > Pointer
virtual unsigned int GetSlice() const
static Pointer New()
BaseRenderer * GetSender() const
Base of all data objects.
Definition: mitkBaseData.h:39
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.
virtual us::ModuleResource GetCursorIconResource() const override
Returns the path of a cursor icon.
void FinishTool()
Finish contour interaction.
static Pointer New()
virtual const char ** GetXPM() const override
Returns an icon in the XPM format.
mitk::ContourElement::VertexIterator VertexIterator
virtual void OnFinish(StateMachineAction *, InteractionEvent *interactionEvent)
Finish LiveWire tool.
#define MITKSEGMENTATION_EXPORT
void FindHighestGradientMagnitudeByITK(itk::Image< TPixel, VImageDimension > *inputImage, itk::Index< 3 > &index, itk::Index< 3 > &returnIndex)
DataCollection - Class to facilitate loading/accessing structured data.
#define MITK_TOOL_MACRO(EXPORT_SPEC, CLASS_NAME, DESCRIPTION)
virtual const PlaneGeometry * GetCurrentWorldPlaneGeometry()
Get the current 2D-worldgeometry (m_CurrentWorldPlaneGeometry) used for 2D-rendering.
const mitk::TimeGeometry * GetTimeGeometry() const
Return the TimeGeometry of the data as const pointer.
Definition: mitkBaseData.h:52
BaseData * GetData() const
Get the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
virtual void OnAddPoint(StateMachineAction *, InteractionEvent *interactionEvent)
Add a control point and finish current segment.
Constants for most interaction classes, due to the generic StateMachines.
A 2D segmentation tool based on LiveWire approach. The contour between the last user added point and ...
Pointer Clone() const
virtual bool OnCheckPoint(const InteractionEvent *interactionEvent)
Check double click on first control point to finish the LiveWire tool.
virtual void OnMouseMoved(StateMachineAction *, InteractionEvent *interactionEvent)
Actual LiveWire computation.
static Pointer New()
virtual void OnLastSegmentDelete(StateMachineAction *, InteractionEvent *interactionEvent)
Close the contour.
void EnableContourLiveWireInteraction(bool on)
Enable interaction with contours. Contours that are created by the tool can be edited using LiveWire ...
#define MITK_WARN
Definition: mitkLogMacros.h:23
void ConfirmSegmentation()
Convert all current contour objects to binary segmentation image.
mitk::DataStorage::Pointer m_DataStorage
virtual mitk::RenderingManager * GetRenderingManager() const
Setter for the RenderingManager that handles this instance of BaseRenderer.
itk::Image< double, 3 > InputImageType
static Pointer New()
#define AccessFixedDimensionByItk_2(mitkImage, itkImageTypeFunction, dimension, arg1, arg2)
static RenderingManager * GetInstance()
Represents an action, that is executed after a certain event (in statemachine-mechanism) TODO: implem...
virtual const char * GetName() const override
Returns the name of this tool. Make it short!
Module * GetModule() const
Image class for storing images.
Definition: mitkImage.h:76
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.
mitk::ContourElement::ConstVertexIterator ConstVertexIterator
std::vcl_size_t TimeStepType
virtual void Activated() override
Called when the tool gets activated.
virtual unsigned int GetTimeStep() const
us::ModuleResource GetIconResource() const override
Returns the tool button icon of the tool wrapped by a usModuleResource.
static Pointer New()
void ClearSegmentation()
Delete all current contour objects.
void RequestUpdate(vtkRenderWindow *renderWindow)
MITKCORE_EXPORT const ScalarType sqrteps
#define CONNECT_CONDITION(a, f)
static Pointer New()
Abstract base class for segmentation tools.
Definition: mitkSegTool2D.h:58
virtual void OnMouseMoveNoDynamicCosts(StateMachineAction *, InteractionEvent *interactionEvent)
Don't use dynamic cost map for LiveWire calculation.
static Pointer New()
virtual bool IsPositionEventInsideImageRegion(InteractionPositionEvent *positionEvent, BaseData *data)
IsPositionEventInsideImageRegion.
#define CONNECT_FUNCTION(a, f)
bool IsInside(const mitk::Point3D &p) const
Test whether the point p (world coordinates in mm) is inside the bounding box.
virtual void OnInitLiveWire(StateMachineAction *, InteractionEvent *interactionEvent)
Initialize tool.
virtual void Remove(const mitk::DataNode *node)=0
Removes node from the DataStorage.
int AddContourmarker()
Adds a new node called Contourmarker to the datastorage which holds a mitk::PlanarFigure. By selecting this node the slicestack will be reoriented according to the PlanarFigure's Geometry.
mitk::BaseGeometry * GetGeometry(int t=0) const
Return the geometry, which is a TimeGeometry, of the data as non-const pointer.
Definition: mitkBaseData.h:129
itk::SmartPointer< Self > Pointer
Definition: mitkBaseData.h:42
static ModuleContext * GetModuleContext()
Returns the module context of the calling module.
vtkRenderWindow * GetRenderWindow() const
Access the RenderWindow into which this renderer renders.
void RequestUpdateAll(RequestType type=REQUEST_UPDATE_ALL)
Class for nodes of the DataTree.
Definition: mitkDataNode.h:66
void ConnectActionsAndFunctions() override
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.