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
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.