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