19 #include "mitkRegionGrowingTool.xpm" 36 #include <itkConnectedComponentImageFilter.h> 37 #include <itkConnectedThresholdImageFilter.h> 38 #include <itkImageRegionIteratorWithIndex.h> 39 #include <itkNeighborhoodIterator.h> 41 #include <itkImageDuplicator.h> 48 #define ROUND(a) ((a) > 0 ? (int)((a) + 0.5) : -(int)(0.5 - (a))) 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)
75 return mitkRegionGrowingTool_xpm;
94 return "Region Growing";
99 Superclass::Activated();
104 Superclass::Deactivated();
108 template <
typename TPixel,
unsigned int imageDimension>
112 unsigned int neighborhood)
115 auto neighborhoodInt = (int)neighborhood;
116 TPixel averageValue(0);
117 unsigned int numberOfPixels = (2 * neighborhood + 1) * (2 * neighborhood + 1);
118 if (imageDimension == 3)
120 numberOfPixels *= (2 * neighborhood + 1);
123 MITK_DEBUG <<
"Getting neighborhood of " << numberOfPixels <<
" pixels around " << index;
127 for (
int i = (0 - neighborhoodInt); i <= neighborhoodInt; ++i)
129 currentIndex[0] = index[0] + i;
131 for (
int j = (0 - neighborhoodInt); j <= neighborhoodInt; ++j)
133 currentIndex[1] = index[1] + j;
135 if (imageDimension == 3)
137 for (
int k = (0 - neighborhoodInt);
k <= neighborhoodInt; ++
k)
139 currentIndex[2] = index[2] +
k;
141 if (itkImage->GetLargestPossibleRegion().IsInside(currentIndex))
143 averageValue += itkImage->GetPixel(currentIndex);
153 if (itkImage->GetLargestPossibleRegion().IsInside(currentIndex))
155 averageValue += itkImage->GetPixel(currentIndex);
166 *result /= numberOfPixels;
170 template <
typename TPixel,
unsigned int imageDimension>
175 if (itkImage->GetPixel(index) > 0)
186 template <
typename TPixel,
unsigned int imageDimension>
189 std::array<ScalarType, 2> thresholds,
192 MITK_DEBUG <<
"Starting region growing at index " << seedIndex <<
" with lower threshold " << thresholds[0]
193 <<
" and upper threshold " << thresholds[1];
196 typedef itk::Image<DefaultSegmentationDataType, imageDimension> OutputImageType;
198 typedef itk::ConnectedThresholdImageFilter<InputImageType, OutputImageType> RegionGrowingFilterType;
199 typename RegionGrowingFilterType::Pointer regionGrower = RegionGrowingFilterType::New();
202 regionGrower->SetInput(inputImage);
203 regionGrower->AddSeed(seedIndex);
205 regionGrower->SetLower(thresholds[0]);
206 regionGrower->SetUpper(thresholds[1]);
210 regionGrower->Update();
217 typename OutputImageType::Pointer resultImage = regionGrower->GetOutput();
220 typedef itk::NeighborhoodIterator<OutputImageType> NeighborhoodIteratorType;
221 typedef itk::ImageRegionIterator<OutputImageType> ImageIteratorType;
223 typename NeighborhoodIteratorType::RadiusType radius;
226 typedef itk::ImageDuplicator< OutputImageType > DuplicatorType;
227 typename DuplicatorType::Pointer duplicator = DuplicatorType::New();
228 duplicator->SetInputImage(resultImage);
229 duplicator->Update();
231 typename OutputImageType::Pointer resultDup = duplicator->GetOutput();
233 NeighborhoodIteratorType neighborhoodIterator(radius, resultDup, resultDup->GetRequestedRegion());
234 ImageIteratorType imageIterator(resultImage, resultImage->GetRequestedRegion());
236 for (neighborhoodIterator.GoToBegin(), imageIterator.GoToBegin(); !neighborhoodIterator.IsAtEnd();
237 ++neighborhoodIterator, ++imageIterator)
242 for (
unsigned int i = 0; i < neighborhoodIterator.Size(); ++i)
244 if (neighborhoodIterator.GetPixel(i) > 0)
254 if (voteYes > voteNo)
256 imageIterator.Set(1);
260 imageIterator.Set(0);
264 if (resultImage.IsNull())
266 MITK_DEBUG <<
"Region growing result is empty.";
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);
299 MITK_DEBUG <<
"OnMousePressed: got working slice";
304 workingSliceGeometry->WorldToIndex(positionEvent->GetPositionInWorld(),
m_SeedPoint);
309 if (workingSliceGeometry->IsIndexInside(
m_SeedPoint))
311 MITK_DEBUG <<
"OnMousePressed: point " << positionEvent->GetPositionInWorld() <<
" (index coordinates " 317 m_PaintingPixelValue = inside ? 0 : 1;
329 MITK_DEBUG <<
"Clicked outside of segmentation";
418 referenceSliceGeometry =
422 referenceSliceGeometry->WorldToIndex(positionEvent->GetPositionInWorld(), indexInReferenceSlice);
423 indexInReferenceSlice2D[0] = indexInReferenceSlice[0];
424 indexInReferenceSlice2D[1] = indexInReferenceSlice[1];
437 MITK_DEBUG <<
"Level window width is " << currentVisibleWindow;
449 resultImage->SetGeometry(workingSliceGeometry);
452 if (resultImage.IsNotNull() && m_ConnectedComponentValue >= 1)
454 float isoOffset = 0.33;
457 contourExtractor->SetInput(resultImage);
458 contourExtractor->SetContourValue(m_ConnectedComponentValue - isoOffset);
459 contourExtractor->Update();
461 resultContour = contourExtractor->GetOutput();
464 if (resultContour.IsNotNull())
470 auto t = positionEvent->GetSender()->GetTimeStep();
474 : resultContourWorld);
487 if (m_PaintingPixelValue == 0)
519 resultImage->SetGeometry(workingSliceGeometry);
522 if (resultImage.IsNotNull() && m_ConnectedComponentValue >= 1)
524 float isoOffset = 0.33;
527 contourExtractor->SetInput(resultImage);
528 contourExtractor->SetContourValue(m_ConnectedComponentValue - isoOffset);
529 contourExtractor->Update();
531 resultContour = contourExtractor->GetOutput();
534 if (resultContour.IsNotNull())
540 int timestep = positionEvent->GetSender()->GetTimeStep();
543 int size = resultContourWorld->GetNumberOfVertices(0);
545 resultContourTimeWorld->Expand(timestep + 1);
546 for (
int loop = 0; loop < size; ++loop)
548 resultContourTimeWorld->AddVertex(resultContourWorld->GetVertexAt(loop, 0), timestep);
568 if (m_PaintingPixelValue == 0)
575 if (
m_WorkingSlice.IsNotNull() && m_FillFeedbackContour && positionEvent)
583 int timestep = positionEvent->GetSender()->GetTimeStep();
588 feedbackContourTime->Expand(timestep + 1);
589 for (
int loop = 0; loop < size; ++loop)
591 feedbackContourTime->AddVertex(feedbackContour->
GetVertexAt(loop, timestep), 0);
604 if (projectedContour.IsNotNull())
614 if (labelImage !=
nullptr)
618 auto activeLabel = labelImage->GetActiveLabel(labelImage->GetActiveLayer())->GetValue();
623 m_PaintingPixelValue * activeLabel);
631 m_PaintingPixelValue);
int GetNumberOfVertices(int timestep=0) const
Returns the number of vertices at a given timestep.
ContourModel is a structure of linked vertices defining a contour in 3D space. The vertices are store...
Super class for all position events.
virtual const VertexType * GetVertexAt(int index, int timestep=0) const
Returns the vertex at the index position within the container.
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.
::mitk::Image InputImageType
#define MITKSEGMENTATION_EXPORT
DataCollection - Class to facilitate loading/accessing structured data.
#define AccessFixedDimensionByItk_3(mitkImage, itkImageTypeFunction, dimension, arg1, arg2, arg3)
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.
MITK_TOOL_MACRO(MITKSEGMENTATION_EXPORT, LiveWireTool2D, "LiveWire tool")
#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
void ForceImmediateUpdate(vtkRenderWindow *renderWindow)
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.
LabelSetImage class for handling labels and layers in a segmentation session.
#define CONNECT_FUNCTION(a, f)
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. ...
Class for nodes of the DataTree.