Medical Imaging Interaction Toolkit  2016.11.0
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,
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.