Medical Imaging Interaction Toolkit  2018.4.99-a3d2e8fb
Medical Imaging Interaction Toolkit
mitkRegionGrowingTool.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 "mitkRegionGrowingTool.h"
14 #include "mitkApplicationCursor.h"
15 #include "mitkBaseRenderer.h"
16 #include "mitkImageDataItem.h"
19 #include "mitkRegionGrowingTool.xpm"
20 #include "mitkRenderingManager.h"
21 #include "mitkToolManager.h"
22 
24 #include "mitkLabelSetImage.h"
26 
27 // us
28 #include <usGetModuleContext.h>
29 #include <usModule.h>
30 #include <usModuleContext.h>
31 #include <usModuleResource.h>
32 
33 // ITK
34 #include "mitkITKImageImport.h"
35 #include "mitkImageAccessByItk.h"
36 #include <itkConnectedComponentImageFilter.h>
37 #include <itkConnectedThresholdImageFilter.h>
38 #include <itkImageRegionIteratorWithIndex.h>
39 #include <itkNeighborhoodIterator.h>
40 
41 #include <itkImageDuplicator.h>
42 
43 namespace mitk
44 {
46 }
47 
48 #define ROUND(a) ((a) > 0 ? (int)((a) + 0.5) : -(int)(0.5 - (a)))
49 
51  : FeedbackContourTool("PressMoveRelease"),
52  m_SeedValue(0),
53  m_ScreenYDifference(0),
54  m_ScreenXDifference(0),
55  m_MouseDistanceScaleFactor(0.5),
56  m_PaintingPixelValue(0),
57  m_FillFeedbackContour(true),
58  m_ConnectedComponentValue(1)
59 {
60 }
61 
63 {
64 }
65 
67 {
68  CONNECT_FUNCTION("PrimaryButtonPressed", OnMousePressed);
71 }
72 
73 const char **mitk::RegionGrowingTool::GetXPM() const
74 {
75  return mitkRegionGrowingTool_xpm;
76 }
77 
79 {
81  us::ModuleResource resource = module->GetResource("RegionGrowing_48x48.png");
82  return resource;
83 }
84 
86 {
88  us::ModuleResource resource = module->GetResource("RegionGrowing_Cursor_32x32.png");
89  return resource;
90 }
91 
93 {
94  return "Region Growing";
95 }
96 
98 {
99  Superclass::Activated();
100 }
101 
103 {
104  Superclass::Deactivated();
105 }
106 
107 // Get the average pixel value of square/cube with radius=neighborhood around index
108 template <typename TPixel, unsigned int imageDimension>
109 void mitk::RegionGrowingTool::GetNeighborhoodAverage(itk::Image<TPixel, imageDimension> *itkImage,
111  ScalarType *result,
112  unsigned int neighborhood)
113 {
114  // maybe assert that image dimension is only 2 or 3?
115  auto neighborhoodInt = (int)neighborhood;
116  TPixel averageValue(0);
117  unsigned int numberOfPixels = (2 * neighborhood + 1) * (2 * neighborhood + 1);
118  if (imageDimension == 3)
119  {
120  numberOfPixels *= (2 * neighborhood + 1);
121  }
122 
123  MITK_DEBUG << "Getting neighborhood of " << numberOfPixels << " pixels around " << index;
124 
125  itk::Index<imageDimension> currentIndex;
126 
127  for (int i = (0 - neighborhoodInt); i <= neighborhoodInt; ++i)
128  {
129  currentIndex[0] = index[0] + i;
130 
131  for (int j = (0 - neighborhoodInt); j <= neighborhoodInt; ++j)
132  {
133  currentIndex[1] = index[1] + j;
134 
135  if (imageDimension == 3)
136  {
137  for (int k = (0 - neighborhoodInt); k <= neighborhoodInt; ++k)
138  {
139  currentIndex[2] = index[2] + k;
140 
141  if (itkImage->GetLargestPossibleRegion().IsInside(currentIndex))
142  {
143  averageValue += itkImage->GetPixel(currentIndex);
144  }
145  else
146  {
147  numberOfPixels -= 1;
148  }
149  }
150  }
151  else
152  {
153  if (itkImage->GetLargestPossibleRegion().IsInside(currentIndex))
154  {
155  averageValue += itkImage->GetPixel(currentIndex);
156  }
157  else
158  {
159  numberOfPixels -= 1;
160  }
161  }
162  }
163  }
164 
165  *result = (ScalarType)averageValue;
166  *result /= numberOfPixels;
167 }
168 
169 // Check whether index lies inside a segmentation
170 template <typename TPixel, unsigned int imageDimension>
171 void mitk::RegionGrowingTool::IsInsideSegmentation(itk::Image<TPixel, imageDimension> *itkImage,
173  bool *result)
174 {
175  if (itkImage->GetPixel(index) > 0)
176  {
177  *result = true;
178  }
179  else
180  {
181  *result = false;
182  }
183 }
184 
185 // Do the region growing (i.e. call an ITK filter that does it)
186 template <typename TPixel, unsigned int imageDimension>
187 void mitk::RegionGrowingTool::StartRegionGrowing(itk::Image<TPixel, imageDimension> *inputImage,
188  itk::Index<imageDimension> seedIndex,
189  std::array<ScalarType, 2> thresholds,
190  mitk::Image::Pointer &outputImage)
191 {
192  MITK_DEBUG << "Starting region growing at index " << seedIndex << " with lower threshold " << thresholds[0]
193  << " and upper threshold " << thresholds[1];
194 
195  typedef itk::Image<TPixel, imageDimension> InputImageType;
196  typedef itk::Image<DefaultSegmentationDataType, imageDimension> OutputImageType;
197 
198  typedef itk::ConnectedThresholdImageFilter<InputImageType, OutputImageType> RegionGrowingFilterType;
199  typename RegionGrowingFilterType::Pointer regionGrower = RegionGrowingFilterType::New();
200 
201  // perform region growing in desired segmented region
202  regionGrower->SetInput(inputImage);
203  regionGrower->AddSeed(seedIndex);
204 
205  regionGrower->SetLower(thresholds[0]);
206  regionGrower->SetUpper(thresholds[1]);
207 
208  try
209  {
210  regionGrower->Update();
211  }
212  catch (...)
213  {
214  return; // Should we do something?
215  }
216 
217  typename OutputImageType::Pointer resultImage = regionGrower->GetOutput();
218 
219  // Smooth result: Every pixel is replaced by the majority of the neighborhood
220  typedef itk::NeighborhoodIterator<OutputImageType> NeighborhoodIteratorType;
221  typedef itk::ImageRegionIterator<OutputImageType> ImageIteratorType;
222 
223  typename NeighborhoodIteratorType::RadiusType radius;
224  radius.Fill(2); // for now, maybe make this something the user can adjust in the preferences?
225 
226  typedef itk::ImageDuplicator< OutputImageType > DuplicatorType;
227  typename DuplicatorType::Pointer duplicator = DuplicatorType::New();
228  duplicator->SetInputImage(resultImage);
229  duplicator->Update();
230 
231  typename OutputImageType::Pointer resultDup = duplicator->GetOutput();
232 
233  NeighborhoodIteratorType neighborhoodIterator(radius, resultDup, resultDup->GetRequestedRegion());
234  ImageIteratorType imageIterator(resultImage, resultImage->GetRequestedRegion());
235 
236  for (neighborhoodIterator.GoToBegin(), imageIterator.GoToBegin(); !neighborhoodIterator.IsAtEnd();
237  ++neighborhoodIterator, ++imageIterator)
238  {
239  DefaultSegmentationDataType voteYes(0);
240  DefaultSegmentationDataType voteNo(0);
241 
242  for (unsigned int i = 0; i < neighborhoodIterator.Size(); ++i)
243  {
244  if (neighborhoodIterator.GetPixel(i) > 0)
245  {
246  voteYes += 1;
247  }
248  else
249  {
250  voteNo += 1;
251  }
252  }
253 
254  if (voteYes > voteNo)
255  {
256  imageIterator.Set(1);
257  }
258  else
259  {
260  imageIterator.Set(0);
261  }
262  }
263 
264  if (resultImage.IsNull())
265  {
266  MITK_DEBUG << "Region growing result is empty.";
267  }
268 
269  // Can potentially have multiple regions, use connected component image filter to label disjunct regions
270  typedef itk::ConnectedComponentImageFilter<OutputImageType, OutputImageType> ConnectedComponentImageFilterType;
271  typename ConnectedComponentImageFilterType::Pointer connectedComponentFilter =
272  ConnectedComponentImageFilterType::New();
273  connectedComponentFilter->SetInput(resultImage);
274  connectedComponentFilter->Update();
275  typename OutputImageType::Pointer resultImageCC = connectedComponentFilter->GetOutput();
276  m_ConnectedComponentValue = resultImageCC->GetPixel(seedIndex);
277 
278  outputImage = mitk::GrabItkImageMemory(resultImageCC);
279 }
280 
282 {
283  auto *positionEvent = dynamic_cast<mitk::InteractionPositionEvent *>(interactionEvent);
284  if (!positionEvent)
285  return;
286 
287  MITK_DEBUG << "OnMousePressed";
288 
289  m_LastEventSender = positionEvent->GetSender();
291  m_LastScreenPosition = positionEvent->GetPointerPositionOnScreen();
292 
293  // ReferenceSlice is from the underlying image, WorkingSlice from the active segmentation (can be empty)
296 
297  if (m_WorkingSlice.IsNotNull()) // can't do anything without a working slice (i.e. a possibly empty segmentation)
298  {
299  MITK_DEBUG << "OnMousePressed: got working slice";
300 
301  // 2. Determine if the user clicked inside or outside of the segmentation/working slice (i.e. the whole volume)
302  mitk::BaseGeometry::Pointer workingSliceGeometry;
303  workingSliceGeometry = m_WorkingSlice->GetGeometry();
304  workingSliceGeometry->WorldToIndex(positionEvent->GetPositionInWorld(), m_SeedPoint);
305  itk::Index<2> indexInWorkingSlice2D;
306  indexInWorkingSlice2D[0] = m_SeedPoint[0];
307  indexInWorkingSlice2D[1] = m_SeedPoint[1];
308 
309  if (workingSliceGeometry->IsIndexInside(m_SeedPoint))
310  {
311  MITK_DEBUG << "OnMousePressed: point " << positionEvent->GetPositionInWorld() << " (index coordinates "
312  << m_SeedPoint << ") is inside working slice";
313 
314  // 3. determine the pixel value under the last click to determine what to do
315  bool inside(true);
316  AccessFixedDimensionByItk_2(m_WorkingSlice, IsInsideSegmentation, 2, indexInWorkingSlice2D, &inside);
317  m_PaintingPixelValue = inside ? 0 : 1;
318 
319  if (inside)
320  {
321  MITK_DEBUG << "Clicked inside segmentation";
322  // For now, we're doing nothing when the user clicks inside the segmentation. Behaviour can be implemented via
323  // OnMousePressedInside()
324  // When you do, be sure to remove the m_PaintingPixelValue check in OnMouseMoved() and OnMouseReleased()
325  return;
326  }
327  else
328  {
329  MITK_DEBUG << "Clicked outside of segmentation";
330  OnMousePressedOutside(nullptr, interactionEvent);
331  }
332  }
333  }
334 }
335 
336 // Use this to implement a behaviour for when the user clicks inside a segmentation (for example remove something)
337 // Old IpPic code is kept as comment for reference
339 {
340  // mitk::InteractionPositionEvent* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>( interactionEvent
341  // );
342  // //const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent()); // checked in
343  // OnMousePressed
344  // // 3.1.1. Create a skeletonization of the segmentation and try to find a nice cut
345  // // apply the skeletonization-and-cut algorithm
346  // // generate contour to remove
347  // // set m_ReferenceSlice = nullptr so nothing will happen during mouse move
348  // // remember to fill the contour with 0 in mouserelease
349  // mitkIpPicDescriptor* segmentationHistory = ipMITKSegmentationCreateGrowerHistory( workingPicSlice,
350  // m_LastWorkingSeed, nullptr ); // free again
351  // if (segmentationHistory)
352  // {
353  // tCutResult cutContour = ipMITKSegmentationGetCutPoints( workingPicSlice, segmentationHistory,
354  // initialWorkingOffset ); // tCutResult is a ipSegmentation type
355  // mitkIpPicFree( segmentationHistory );
356  // if (cutContour.cutIt)
357  // {
358  // int timestep = positionEvent->GetSender()->GetTimeStep();
359  // // 3.1.2 copy point from float* to mitk::Contour
360  // ContourModel::Pointer contourInImageIndexCoordinates = ContourModel::New();
361  // contourInImageIndexCoordinates->Expand(timestep + 1);
362  // contourInImageIndexCoordinates->SetClosed(true, timestep);
363  // Point3D newPoint;
364  // for (int index = 0; index < cutContour.deleteSize; ++index)
365  // {
366  // newPoint[0] = cutContour.deleteCurve[ 2 * index + 0 ] - 0.5;//correction is needed because the
367  // output of the algorithm is center based
368  // newPoint[1] = cutContour.deleteCurve[ 2 * index + 1 ] - 0.5;//and we want our contour displayed
369  // corner based.
370  // newPoint[2] = 0.0;
371 
372  // contourInImageIndexCoordinates->AddVertex( newPoint, timestep );
373  // }
374 
375  // free(cutContour.traceline);
376  // free(cutContour.deleteCurve); // perhaps visualize this for fun?
377  // free(cutContour.onGradient);
378 
379  // ContourModel::Pointer contourInWorldCoordinates = FeedbackContourTool::BackProjectContourFrom2DSlice(
380  // m_WorkingSlice->GetGeometry(), contourInImageIndexCoordinates, true ); // true: sub 0.5 for
381  // ipSegmentation correction
382 
383  // FeedbackContourTool::SetFeedbackContour( contourInWorldCoordinates );
384  // FeedbackContourTool::SetFeedbackContourVisible(true);
385  // mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() );
386  // m_FillFeedbackContour = true;
387  // }
388  // else
389  // {
390  // m_FillFeedbackContour = false;
391  // }
392 
393  // }
394  // else
395  // {
396  // m_FillFeedbackContour = false;
397  // }
398 
399  // m_ReferenceSlice = nullptr;
400 
401  // return true;
402 }
403 
405 {
406  auto *positionEvent = dynamic_cast<mitk::InteractionPositionEvent *>(interactionEvent);
407 
408  if (positionEvent)
409  {
410  // Get geometry and indices
411  mitk::BaseGeometry::Pointer workingSliceGeometry;
412  workingSliceGeometry = m_WorkingSlice->GetGeometry();
413  itk::Index<2> indexInWorkingSlice2D;
414  indexInWorkingSlice2D[0] = m_SeedPoint[0];
415  indexInWorkingSlice2D[1] = m_SeedPoint[1];
416 
417  mitk::BaseGeometry::Pointer referenceSliceGeometry;
418  referenceSliceGeometry =
419  m_ReferenceSlice->GetGeometry();
420  itk::Index<3> indexInReferenceSlice;
421  itk::Index<2> indexInReferenceSlice2D;
422  referenceSliceGeometry->WorldToIndex(positionEvent->GetPositionInWorld(), indexInReferenceSlice);
423  indexInReferenceSlice2D[0] = indexInReferenceSlice[0];
424  indexInReferenceSlice2D[1] = indexInReferenceSlice[1];
425 
426  // Get seed neighborhood
427  ScalarType averageValue(0);
428  AccessFixedDimensionByItk_3(m_ReferenceSlice, GetNeighborhoodAverage, 2, indexInReferenceSlice2D, &averageValue, 1);
429  m_SeedValue = averageValue;
430  MITK_DEBUG << "Seed value is " << m_SeedValue;
431 
432  // Get level window settings
433  LevelWindow lw(0, 500); // default window 0 to 500, can we do something smarter here?
434  m_ToolManager->GetReferenceData(0)->GetLevelWindow(
435  lw); // will fill lw if levelwindow property is present, otherwise won't touch it.
436  ScalarType currentVisibleWindow = lw.GetWindow();
437  MITK_DEBUG << "Level window width is " << currentVisibleWindow;
438  m_InitialThresholds[0] = m_SeedValue - currentVisibleWindow / 20.0; // 20 is arbitrary (though works reasonably
439  // well), is there a better alternative (maybe
440  // option in preferences)?
441  m_InitialThresholds[1] = m_SeedValue + currentVisibleWindow / 20.0;
444 
445  // Perform region growing
446  mitk::Image::Pointer resultImage = mitk::Image::New();
448  m_ReferenceSlice, StartRegionGrowing, 2, indexInWorkingSlice2D, m_Thresholds, resultImage);
449  resultImage->SetGeometry(workingSliceGeometry);
450 
451  // Extract contour
452  if (resultImage.IsNotNull() && m_ConnectedComponentValue >= 1)
453  {
454  float isoOffset = 0.33;
455 
457  contourExtractor->SetInput(resultImage);
458  contourExtractor->SetContourValue(m_ConnectedComponentValue - isoOffset);
459  contourExtractor->Update();
460  ContourModel::Pointer resultContour = ContourModel::New();
461  resultContour = contourExtractor->GetOutput();
462 
463  // Show contour
464  if (resultContour.IsNotNull())
465  {
467  workingSliceGeometry, FeedbackContourTool::ProjectContourTo2DSlice(m_WorkingSlice, resultContour));
468 
469  // this is not a beautiful solution, just one that works, check T22412 for details
470  auto t = positionEvent->GetSender()->GetTimeStep();
471 
473  ? ContourModelUtils::MoveZerothContourTimeStep(resultContourWorld, t)
474  : resultContourWorld);
475 
478  }
479  }
480  }
481 }
482 
484 {
485  // Until OnMousePressedInside() implements a behaviour, we're just returning here whenever m_PaintingPixelValue is 0,
486  // i.e. when the user clicked inside the segmentation
487  if (m_PaintingPixelValue == 0)
488  {
489  return;
490  }
491 
492  auto *positionEvent = dynamic_cast<mitk::InteractionPositionEvent *>(interactionEvent);
493 
494  if (m_ReferenceSlice.IsNotNull() && positionEvent)
495  {
496  // Get geometry and indices
497  mitk::BaseGeometry::Pointer workingSliceGeometry;
498  workingSliceGeometry = m_WorkingSlice->GetGeometry();
499  itk::Index<2> indexInWorkingSlice2D;
500  indexInWorkingSlice2D[0] = m_SeedPoint[0];
501  indexInWorkingSlice2D[1] = m_SeedPoint[1];
502 
503  m_ScreenYDifference += positionEvent->GetPointerPositionOnScreen()[1] - m_LastScreenPosition[1];
504  m_ScreenXDifference += positionEvent->GetPointerPositionOnScreen()[0] - m_LastScreenPosition[0];
505  m_LastScreenPosition = positionEvent->GetPointerPositionOnScreen();
506 
507  // Moving the mouse up and down adjusts the width of the threshold window, moving it left and right shifts the
508  // threshold window
509  m_Thresholds[0] = std::min<ScalarType>(
510  m_SeedValue, m_InitialThresholds[0] - (m_ScreenYDifference - m_ScreenXDifference) * m_MouseDistanceScaleFactor);
511  m_Thresholds[1] = std::max<ScalarType>(
512  m_SeedValue, m_InitialThresholds[1] + (m_ScreenYDifference + m_ScreenXDifference) * m_MouseDistanceScaleFactor);
513  MITK_DEBUG << "Screen difference X: " << m_ScreenXDifference;
514 
515  // Perform region growing again and show the result
516  mitk::Image::Pointer resultImage = mitk::Image::New();
518  m_ReferenceSlice, StartRegionGrowing, 2, indexInWorkingSlice2D, m_Thresholds, resultImage);
519  resultImage->SetGeometry(workingSliceGeometry);
520 
521  // Update the contour
522  if (resultImage.IsNotNull() && m_ConnectedComponentValue >= 1)
523  {
524  float isoOffset = 0.33;
525 
527  contourExtractor->SetInput(resultImage);
528  contourExtractor->SetContourValue(m_ConnectedComponentValue - isoOffset);
529  contourExtractor->Update();
530  ContourModel::Pointer resultContour = ContourModel::New();
531  resultContour = contourExtractor->GetOutput();
532 
533  // Show contour
534  if (resultContour.IsNotNull())
535  {
537  workingSliceGeometry, FeedbackContourTool::ProjectContourTo2DSlice(m_WorkingSlice, resultContour));
538 
539  // this is not a beautiful solution, just one that works, check T22412 for details
540  int timestep = positionEvent->GetSender()->GetTimeStep();
541  if (0 != timestep)
542  {
543  int size = resultContourWorld->GetNumberOfVertices(0);
544  auto resultContourTimeWorld = mitk::ContourModel::New();
545  resultContourTimeWorld->Expand(timestep + 1);
546  for (int loop = 0; loop < size; ++loop)
547  {
548  resultContourTimeWorld->AddVertex(resultContourWorld->GetVertexAt(loop, 0), timestep);
549  }
550  FeedbackContourTool::SetFeedbackContour(resultContourTimeWorld);
551  }
552  else
553  {
554  FeedbackContourTool::SetFeedbackContour(resultContourWorld);
555  }
556 
558  mitk::RenderingManager::GetInstance()->ForceImmediateUpdate(positionEvent->GetSender()->GetRenderWindow());
559  }
560  }
561  }
562 }
563 
565 {
566  // Until OnMousePressedInside() implements a behaviour, we're just returning here whenever m_PaintingPixelValue is 0,
567  // i.e. when the user clicked inside the segmentation
568  if (m_PaintingPixelValue == 0)
569  {
570  return;
571  }
572 
573  auto *positionEvent = dynamic_cast<mitk::InteractionPositionEvent *>(interactionEvent);
574 
575  if (m_WorkingSlice.IsNotNull() && m_FillFeedbackContour && positionEvent)
576  {
577  // Project contour into working slice
579 
580  ContourModel::Pointer projectedContour;
581 
582  // this is not a beautiful solution, just one that works, check T22412 for details
583  int timestep = positionEvent->GetSender()->GetTimeStep();
584  if (0 != timestep)
585  {
586  int size = feedbackContour->GetNumberOfVertices(timestep);
587  auto feedbackContourTime = mitk::ContourModel::New();
588  feedbackContourTime->Expand(timestep + 1);
589  for (int loop = 0; loop < size; ++loop)
590  {
591  feedbackContourTime->AddVertex(feedbackContour->GetVertexAt(loop, timestep), 0);
592  }
593 
594  projectedContour =
595  FeedbackContourTool::ProjectContourTo2DSlice(m_WorkingSlice, feedbackContourTime, false, false);
596  }
597  else
598  {
599  projectedContour =
600  FeedbackContourTool::ProjectContourTo2DSlice(m_WorkingSlice, feedbackContour, false, false);
601  }
602 
603  // If there is a projected contour, fill it
604  if (projectedContour.IsNotNull())
605  {
606  // Get working data to pass to following method so we don't overwrite locked labels in a LabelSetImage
607  mitk::DataNode *workingNode(m_ToolManager->GetWorkingData(0));
608  mitk::LabelSetImage *labelImage = workingNode != nullptr
609  ? dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData())
610  : nullptr;
611 
612  MITK_DEBUG << "Filling Segmentation";
613 
614  if (labelImage != nullptr)
615  {
616  // m_PaintingPixelValue only decides whether to paint or not
617  // For LabelSetImages we want to paint with the active label value
618  auto activeLabel = labelImage->GetActiveLabel(labelImage->GetActiveLayer())->GetValue();
620  0,
622  labelImage,
623  m_PaintingPixelValue * activeLabel);
624  }
625  else
626  {
628  0,
631  m_PaintingPixelValue);
632  }
633  this->WriteBackSegmentationResult(positionEvent, m_WorkingSlice);
635  }
636 
639  }
640 }
void Activated() override
Called when the tool gets activated.
int GetNumberOfVertices(int timestep=0) const
Returns the number of vertices at a given timestep.
unsigned int m_LastEventSlice
ContourModel is a structure of linked vertices defining a contour in 3D space. The vertices are store...
Super class for all position events.
float k(1.0)
void SetFeedbackContour(ContourModel::Pointer)
std::array< ScalarType, 2 > m_InitialThresholds
virtual const VertexType * GetVertexAt(int index, int timestep=0) const
Returns the vertex at the index position within the container.
us::ModuleResource GetCursorIconResource() const override
Returns the path of a cursor icon.
virtual unsigned int GetSlice() const
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.
double ScalarType
const char ** GetXPM() const override
Returns an icon in the XPM format.
void StartRegionGrowing(itk::Image< TPixel, imageDimension > *itkImage, itk::Index< imageDimension > seedPoint, std::array< ScalarType, 2 > thresholds, mitk::Image::Pointer &outputImage)
Template that calls an ITK filter to do the region growing.
const char * GetName() const override
Returns the name of this tool. Make it short!
#define MITK_DEBUG
Definition: mitkLogMacros.h:22
#define MITKSEGMENTATION_EXPORT
DataCollection - Class to facilitate loading/accessing structured data.
std::array< ScalarType, 2 > m_Thresholds
us::ModuleResource GetIconResource() const override
Returns the tool button icon of the tool wrapped by a usModuleResource.
BaseRenderer * m_LastEventSender
Image::Pointer GetAffectedReferenceSlice(const InteractionPositionEvent *)
Extract the slice of the currently selected reference image that the user just scribbles on...
#define AccessFixedDimensionByItk_3(mitkImage, itkImageTypeFunction, dimension, arg1, arg2, arg3)
void Deactivated() override
Called when the tool gets deactivated.
Image::Pointer GrabItkImageMemory(itk::SmartPointer< ItkOutputImageType > &itkimage, mitk::Image *mitkImage=nullptr, const BaseGeometry *geometry=nullptr, bool update=true)
Grabs the memory of an itk::Image (with a specific type) and puts it into an mitk::Image.The memory is managed by the mitk::Image after calling this function. The itk::Image remains valid until the mitk::Image decides to free the memory.
The LevelWindow class Class to store level/window values.
virtual void OnMouseReleased(StateMachineAction *, InteractionEvent *interactionEvent)
OnMouseReleased converts the feedback contour to a segmentation.
virtual void OnMousePressed(StateMachineAction *, InteractionEvent *interactionEvent)
OnMousePressed is called when the user clicks. Calls either OnMousePressedInside() or OnMousePressedO...
void IsInsideSegmentation(itk::Image< TPixel, imageDimension > *itkImage, itk::Index< imageDimension > index, bool *result)
Template to check whether index is inside already segmented area.
MITK_TOOL_MACRO(MITKSEGMENTATION_EXPORT, LiveWireTool2D, "LiveWire tool")
A slice based region growing tool.
virtual void OnMouseMoved(StateMachineAction *, InteractionEvent *interactionEvent)
OnMouseMoved is called when the user moves the mouse with the left mouse button pressed. Adjusts the thresholds. Up: Increase upper threshold, decrease lower threshold. Down: Decrease upper threshold, increase lower threshold. Right: Increase both thresholds. Left: Decrease both thresholds.
#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...
Module * GetModule() const
ModuleResource GetResource(const std::string &path) const
Definition: usModule.cpp:267
void WriteBackSegmentationResult(const InteractionPositionEvent *, Image *)
ContourModel::Pointer ProjectContourTo2DSlice(Image *slice, ContourModel *contourIn3D, bool correctionForIpSegmentation=false, bool constrainToInside=true)
Projects a contour onto an image point by point. Converts from world to index coordinates.
void ForceImmediateUpdate(vtkRenderWindow *renderWindow)
virtual void OnMousePressedOutside(StateMachineAction *, InteractionEvent *interactionEvent)
OnMousePressedOutside is called when the user clicks outside of the segmented area. Grows a region.
ContourModel::Pointer BackProjectContourFrom2DSlice(const BaseGeometry *sliceGeometry, ContourModel *contourIn2D, bool correctionForIpSegmentation=false)
Projects a slice index coordinates of a contour back into world coordinates.
static Pointer New()
ScalarType GetWindow() const
returns the current window size, i.e the range size of the current grey value interval ...
void RequestUpdate(vtkRenderWindow *renderWindow)
vtkRenderWindow * GetRenderWindow() const
Access the RenderWindow into which this renderer renders.
Base class for tools that use a contour for feedback.
void ConnectActionsAndFunctions() override
mitk::Label::PixelType DefaultSegmentationDataType
Definition: mitkTool.h:89
DataVectorType GetReferenceData()
LabelSetImage class for handling labels and layers in a segmentation session.
ToolManager * m_ToolManager
Definition: mitkTool.h:228
static Pointer New()
#define CONNECT_FUNCTION(a, f)
virtual void OnMousePressedInside()
OnMousePressedInside can be used to implement behaviour when the user clicks inside a segmentation...
static ModuleContext * GetModuleContext()
Returns the module context of the calling module.
static ContourModel::Pointer MoveZerothContourTimeStep(const ContourModel *contour, unsigned int timeStep)
Move the contour in time step 0 to to a new contour model at the given time step. ...
void GetNeighborhoodAverage(itk::Image< TPixel, imageDimension > *itkImage, itk::Index< imageDimension > index, ScalarType *result, unsigned int neighborhood=1)
Template to calculate average pixel value around index using a square/cube with radius neighborhood...
Image::Pointer GetAffectedWorkingSlice(const InteractionPositionEvent *)
Extract the slice of the currently selected working image that the user just scribbles on...
Class for nodes of the DataTree.
Definition: mitkDataNode.h:57
DataVectorType GetWorkingData()