diff --git a/Modules/Segmentation/Interactions/mitkRegionGrowingTool.cpp b/Modules/Segmentation/Interactions/mitkRegionGrowingTool.cpp index 2bc6b9c576..0f5dbe1d43 100644 --- a/Modules/Segmentation/Interactions/mitkRegionGrowingTool.cpp +++ b/Modules/Segmentation/Interactions/mitkRegionGrowingTool.cpp @@ -1,510 +1,448 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkRegionGrowingTool.h" #include "mitkBaseRenderer.h" #include "mitkImageToContourModelFilter.h" #include "mitkRegionGrowingTool.xpm" #include "mitkRenderingManager.h" #include "mitkToolManager.h" // us #include #include #include #include // ITK #include "mitkITKImageImport.h" #include "mitkImageAccessByItk.h" #include #include #include #include #include namespace mitk { MITK_TOOL_MACRO(MITKSEGMENTATION_EXPORT, RegionGrowingTool, "Region growing tool"); } #define ROUND(a) ((a) > 0 ? (int)((a) + 0.5) : -(int)(0.5 - (a))) mitk::RegionGrowingTool::RegionGrowingTool() : FeedbackContourTool("PressMoveRelease"), m_SeedValue(0), m_ScreenYDifference(0), m_ScreenXDifference(0), m_MouseDistanceScaleFactor(0.5), - m_PaintingPixelValue(0), + m_PaintingPixelValue(1), m_FillFeedbackContour(true), m_ConnectedComponentValue(1) { } mitk::RegionGrowingTool::~RegionGrowingTool() { } void mitk::RegionGrowingTool::ConnectActionsAndFunctions() { CONNECT_FUNCTION("PrimaryButtonPressed", OnMousePressed); CONNECT_FUNCTION("Move", OnMouseMoved); CONNECT_FUNCTION("Release", OnMouseReleased); } const char **mitk::RegionGrowingTool::GetXPM() const { return mitkRegionGrowingTool_xpm; } us::ModuleResource mitk::RegionGrowingTool::GetIconResource() const { us::Module *module = us::GetModuleContext()->GetModule(); us::ModuleResource resource = module->GetResource("RegionGrowing_48x48.png"); return resource; } us::ModuleResource mitk::RegionGrowingTool::GetCursorIconResource() const { us::Module *module = us::GetModuleContext()->GetModule(); us::ModuleResource resource = module->GetResource("RegionGrowing_Cursor_32x32.png"); return resource; } const char *mitk::RegionGrowingTool::GetName() const { return "Region Growing"; } void mitk::RegionGrowingTool::Activated() { Superclass::Activated(); } void mitk::RegionGrowingTool::Deactivated() { Superclass::Deactivated(); } // Get the average pixel value of square/cube with radius=neighborhood around index template void mitk::RegionGrowingTool::GetNeighborhoodAverage(const itk::Image *itkImage, const itk::Index& index, ScalarType *result, unsigned int neighborhood) { // maybe assert that image dimension is only 2 or 3? auto neighborhoodInt = (int)neighborhood; TPixel averageValue(0); unsigned int numberOfPixels = (2 * neighborhood + 1) * (2 * neighborhood + 1); if (imageDimension == 3) { numberOfPixels *= (2 * neighborhood + 1); } MITK_DEBUG << "Getting neighborhood of " << numberOfPixels << " pixels around " << index; itk::Index currentIndex; for (int i = (0 - neighborhoodInt); i <= neighborhoodInt; ++i) { currentIndex[0] = index[0] + i; for (int j = (0 - neighborhoodInt); j <= neighborhoodInt; ++j) { currentIndex[1] = index[1] + j; if (imageDimension == 3) { for (int k = (0 - neighborhoodInt); k <= neighborhoodInt; ++k) { currentIndex[2] = index[2] + k; if (itkImage->GetLargestPossibleRegion().IsInside(currentIndex)) { averageValue += itkImage->GetPixel(currentIndex); } else { numberOfPixels -= 1; } } } else { if (itkImage->GetLargestPossibleRegion().IsInside(currentIndex)) { averageValue += itkImage->GetPixel(currentIndex); } else { numberOfPixels -= 1; } } } } *result = (ScalarType)averageValue; *result /= numberOfPixels; } -// Check whether index lies inside a segmentation -template -void mitk::RegionGrowingTool::IsInsideSegmentation(const itk::Image *itkImage, - const itk::Index& index, - bool *result) -{ - if (itkImage->GetPixel(index) > 0) - { - *result = true; - } - else - { - *result = false; - } -} - // Do the region growing (i.e. call an ITK filter that does it) template void mitk::RegionGrowingTool::StartRegionGrowing(const itk::Image *inputImage, const itk::Index& seedIndex, const std::array& thresholds, mitk::Image::Pointer &outputImage) { MITK_DEBUG << "Starting region growing at index " << seedIndex << " with lower threshold " << thresholds[0] << " and upper threshold " << thresholds[1]; typedef itk::Image InputImageType; typedef itk::Image OutputImageType; typedef itk::ConnectedThresholdImageFilter RegionGrowingFilterType; typename RegionGrowingFilterType::Pointer regionGrower = RegionGrowingFilterType::New(); // perform region growing in desired segmented region regionGrower->SetInput(inputImage); regionGrower->SetSeed(seedIndex); regionGrower->SetLower(thresholds[0]); regionGrower->SetUpper(thresholds[1]); try { regionGrower->Update(); } catch (...) { return; // Should we do something? } typename OutputImageType::Pointer resultImage = regionGrower->GetOutput(); // Smooth result: Every pixel is replaced by the majority of the neighborhood typedef itk::NeighborhoodIterator NeighborhoodIteratorType; typedef itk::ImageRegionIterator ImageIteratorType; typename NeighborhoodIteratorType::RadiusType radius; radius.Fill(2); // for now, maybe make this something the user can adjust in the preferences? typedef itk::ImageDuplicator< OutputImageType > DuplicatorType; typename DuplicatorType::Pointer duplicator = DuplicatorType::New(); duplicator->SetInputImage(resultImage); duplicator->Update(); typename OutputImageType::Pointer resultDup = duplicator->GetOutput(); NeighborhoodIteratorType neighborhoodIterator(radius, resultDup, resultDup->GetRequestedRegion()); ImageIteratorType imageIterator(resultImage, resultImage->GetRequestedRegion()); for (neighborhoodIterator.GoToBegin(), imageIterator.GoToBegin(); !neighborhoodIterator.IsAtEnd(); ++neighborhoodIterator, ++imageIterator) { DefaultSegmentationDataType voteYes(0); DefaultSegmentationDataType voteNo(0); for (unsigned int i = 0; i < neighborhoodIterator.Size(); ++i) { if (neighborhoodIterator.GetPixel(i) > 0) { voteYes += 1; } else { voteNo += 1; } } if (voteYes > voteNo) { imageIterator.Set(1); } else { imageIterator.Set(0); } } if (resultImage.IsNull()) { MITK_DEBUG << "Region growing result is empty."; } // Can potentially have multiple regions, use connected component image filter to label disjunct regions typedef itk::ConnectedComponentImageFilter ConnectedComponentImageFilterType; typename ConnectedComponentImageFilterType::Pointer connectedComponentFilter = ConnectedComponentImageFilterType::New(); connectedComponentFilter->SetInput(resultImage); connectedComponentFilter->Update(); typename OutputImageType::Pointer resultImageCC = connectedComponentFilter->GetOutput(); m_ConnectedComponentValue = resultImageCC->GetPixel(seedIndex); outputImage = mitk::GrabItkImageMemory(resultImageCC); } template void mitk::RegionGrowingTool::CalculateInitialThresholds(const itk::Image*) { LevelWindow levelWindow; this->GetToolManager()->GetReferenceData(0)->GetLevelWindow(levelWindow); m_ThresholdExtrema[0] = static_cast(std::numeric_limits::lowest()); m_ThresholdExtrema[1] = static_cast(std::numeric_limits::max()); const ScalarType lowerWindowBound = std::max(m_ThresholdExtrema[0], levelWindow.GetLowerWindowBound()); const ScalarType upperWindowBound = std::min(m_ThresholdExtrema[1], levelWindow.GetUpperWindowBound()); if (m_SeedValue < lowerWindowBound) { m_InitialThresholds = { m_ThresholdExtrema[0], lowerWindowBound }; } else if (m_SeedValue > upperWindowBound) { m_InitialThresholds = { upperWindowBound, m_ThresholdExtrema[1] }; } else { const ScalarType range = 0.1 * (upperWindowBound - lowerWindowBound); // 10% of the visible window m_InitialThresholds[0] = std::min(std::max(lowerWindowBound, m_SeedValue - 0.5 * range), upperWindowBound - range); m_InitialThresholds[1] = m_InitialThresholds[0] + range; } } -void mitk::RegionGrowingTool::OnMousePressed(StateMachineAction *, InteractionEvent *interactionEvent) +void mitk::RegionGrowingTool::OnMousePressed(StateMachineAction*, InteractionEvent* interactionEvent) { - auto *positionEvent = dynamic_cast(interactionEvent); - if (!positionEvent) + auto* positionEvent = dynamic_cast(interactionEvent); + if (nullptr == positionEvent) + { return; + } m_LastEventSender = positionEvent->GetSender(); m_LastEventSlice = m_LastEventSender->GetSlice(); m_LastScreenPosition = Point2I(positionEvent->GetPointerPositionOnScreen()); // ReferenceSlice is from the underlying image, WorkingSlice from the active segmentation (can be empty) m_ReferenceSlice = FeedbackContourTool::GetAffectedReferenceSlice(positionEvent); m_WorkingSlice = FeedbackContourTool::GetAffectedWorkingSlice(positionEvent); - if (m_WorkingSlice.IsNotNull()) // can't do anything without a working slice (i.e. a possibly empty segmentation) + if (m_WorkingSlice.IsNull()) { - // 2. Determine if the user clicked inside or outside of the segmentation/working slice (i.e. the whole volume) - mitk::BaseGeometry::Pointer workingSliceGeometry; - workingSliceGeometry = m_WorkingSlice->GetGeometry(); - workingSliceGeometry->WorldToIndex(positionEvent->GetPositionInWorld(), m_SeedPoint); - itk::Index<2> indexInWorkingSlice2D; - indexInWorkingSlice2D[0] = m_SeedPoint[0]; - indexInWorkingSlice2D[1] = m_SeedPoint[1]; - - if (workingSliceGeometry->IsIndexInside(m_SeedPoint)) - { - MITK_DEBUG << "OnMousePressed: point " << positionEvent->GetPositionInWorld() << " (index coordinates " - << m_SeedPoint << ") is inside working slice"; - - // 3. determine the pixel value under the last click to determine what to do - bool inside(true); - AccessFixedDimensionByItk_2(m_WorkingSlice, IsInsideSegmentation, 2, indexInWorkingSlice2D, &inside); - m_PaintingPixelValue = inside ? 0 : 1; - - if (inside) - { - MITK_DEBUG << "Clicked inside segmentation"; - // For now, we're doing nothing when the user clicks inside the segmentation. Behaviour can be implemented via - // OnMousePressedInside() - // When you do, be sure to remove the m_PaintingPixelValue check in OnMouseMoved() and OnMouseReleased() - return; - } - else - { - MITK_DEBUG << "Clicked outside of segmentation"; - OnMousePressedOutside(nullptr, interactionEvent); - } - } + // can't do anything without a working slice (i.e. a possibly empty segmentation) + return; } -} -// Use this to implement a behaviour for when the user clicks inside a segmentation (for example remove something) -void mitk::RegionGrowingTool::OnMousePressedInside() -{ -} + // Determine if the user clicked inside or outside of the working slice (i.e. the whole volume) + mitk::BaseGeometry::Pointer workingSliceGeometry; + workingSliceGeometry = m_WorkingSlice->GetGeometry(); + workingSliceGeometry->WorldToIndex(positionEvent->GetPositionInWorld(), m_SeedPoint); + itk::Index<2> indexInWorkingSlice2D; + indexInWorkingSlice2D[0] = m_SeedPoint[0]; + indexInWorkingSlice2D[1] = m_SeedPoint[1]; -void mitk::RegionGrowingTool::OnMousePressedOutside(StateMachineAction *, InteractionEvent *interactionEvent) -{ - auto *positionEvent = dynamic_cast(interactionEvent); + if (!workingSliceGeometry->IsIndexInside(m_SeedPoint)) + { + MITK_DEBUG << "OnMousePressed: point " << positionEvent->GetPositionInWorld() << " (index coordinates " + << m_SeedPoint << ") is not inside working slice"; + return; + } - if (positionEvent) + mitk::BaseGeometry::Pointer referenceSliceGeometry; + referenceSliceGeometry = m_ReferenceSlice->GetGeometry(); + itk::Index<3> indexInReferenceSlice; + itk::Index<2> indexInReferenceSlice2D; + referenceSliceGeometry->WorldToIndex(positionEvent->GetPositionInWorld(), indexInReferenceSlice); + indexInReferenceSlice2D[0] = indexInReferenceSlice[0]; + indexInReferenceSlice2D[1] = indexInReferenceSlice[1]; + + // Get seed neighborhood + ScalarType averageValue(0); + AccessFixedDimensionByItk_3(m_ReferenceSlice, GetNeighborhoodAverage, 2, indexInReferenceSlice2D, &averageValue, 1); + m_SeedValue = averageValue; + MITK_DEBUG << "Seed value is " << m_SeedValue; + + // Calculate initial thresholds + AccessFixedDimensionByItk(m_ReferenceSlice, CalculateInitialThresholds, 2); + m_Thresholds[0] = m_InitialThresholds[0]; + m_Thresholds[1] = m_InitialThresholds[1]; + + // Perform region growing + mitk::Image::Pointer resultImage = mitk::Image::New(); + AccessFixedDimensionByItk_3( + m_ReferenceSlice, StartRegionGrowing, 2, indexInWorkingSlice2D, m_Thresholds, resultImage); + resultImage->SetGeometry(workingSliceGeometry); + + // Extract contour + if (resultImage.IsNotNull() && m_ConnectedComponentValue >= 1) { - // Get geometry and indices - mitk::BaseGeometry::Pointer workingSliceGeometry; - workingSliceGeometry = m_WorkingSlice->GetGeometry(); - itk::Index<2> indexInWorkingSlice2D; - indexInWorkingSlice2D[0] = m_SeedPoint[0]; - indexInWorkingSlice2D[1] = m_SeedPoint[1]; + float isoOffset = 0.33; - mitk::BaseGeometry::Pointer referenceSliceGeometry; - referenceSliceGeometry = - m_ReferenceSlice->GetGeometry(); - itk::Index<3> indexInReferenceSlice; - itk::Index<2> indexInReferenceSlice2D; - referenceSliceGeometry->WorldToIndex(positionEvent->GetPositionInWorld(), indexInReferenceSlice); - indexInReferenceSlice2D[0] = indexInReferenceSlice[0]; - indexInReferenceSlice2D[1] = indexInReferenceSlice[1]; - - // Get seed neighborhood - ScalarType averageValue(0); - AccessFixedDimensionByItk_3(m_ReferenceSlice, GetNeighborhoodAverage, 2, indexInReferenceSlice2D, &averageValue, 1); - m_SeedValue = averageValue; - MITK_DEBUG << "Seed value is " << m_SeedValue; - - // Calculate initial thresholds - AccessFixedDimensionByItk(m_ReferenceSlice, CalculateInitialThresholds, 2); - m_Thresholds[0] = m_InitialThresholds[0]; - m_Thresholds[1] = m_InitialThresholds[1]; - - // Perform region growing - mitk::Image::Pointer resultImage = mitk::Image::New(); - AccessFixedDimensionByItk_3( - m_ReferenceSlice, StartRegionGrowing, 2, indexInWorkingSlice2D, m_Thresholds, resultImage); - resultImage->SetGeometry(workingSliceGeometry); + mitk::ImageToContourModelFilter::Pointer contourExtractor = mitk::ImageToContourModelFilter::New(); + contourExtractor->SetInput(resultImage); + contourExtractor->SetContourValue(m_ConnectedComponentValue - isoOffset); + contourExtractor->Update(); + ContourModel::Pointer resultContour = ContourModel::New(); + resultContour = contourExtractor->GetOutput(); - // Extract contour - if (resultImage.IsNotNull() && m_ConnectedComponentValue >= 1) + // Show contour + if (resultContour.IsNotNull()) { - float isoOffset = 0.33; + ContourModel::Pointer resultContourWorld = FeedbackContourTool::BackProjectContourFrom2DSlice( + workingSliceGeometry, FeedbackContourTool::ProjectContourTo2DSlice(m_WorkingSlice, resultContour)); - mitk::ImageToContourModelFilter::Pointer contourExtractor = mitk::ImageToContourModelFilter::New(); - contourExtractor->SetInput(resultImage); - contourExtractor->SetContourValue(m_ConnectedComponentValue - isoOffset); - contourExtractor->Update(); - ContourModel::Pointer resultContour = ContourModel::New(); - resultContour = contourExtractor->GetOutput(); - - // Show contour - if (resultContour.IsNotNull()) - { - ContourModel::Pointer resultContourWorld = FeedbackContourTool::BackProjectContourFrom2DSlice( - workingSliceGeometry, FeedbackContourTool::ProjectContourTo2DSlice(m_WorkingSlice, resultContour)); - - FeedbackContourTool::UpdateCurrentFeedbackContour(resultContourWorld); + FeedbackContourTool::UpdateCurrentFeedbackContour(resultContourWorld); - FeedbackContourTool::SetFeedbackContourVisible(true); - mitk::RenderingManager::GetInstance()->RequestUpdate(m_LastEventSender->GetRenderWindow()); - } + FeedbackContourTool::SetFeedbackContourVisible(true); + mitk::RenderingManager::GetInstance()->RequestUpdate(m_LastEventSender->GetRenderWindow()); } } } void mitk::RegionGrowingTool::OnMouseMoved(StateMachineAction *, InteractionEvent *interactionEvent) { - // Until OnMousePressedInside() implements a behaviour, we're just returning here whenever m_PaintingPixelValue is 0, - // i.e. when the user clicked inside the segmentation - if (m_PaintingPixelValue == 0) - { - return; - } auto *positionEvent = dynamic_cast(interactionEvent); if (m_ReferenceSlice.IsNotNull() && positionEvent) { // Get geometry and indices mitk::BaseGeometry::Pointer workingSliceGeometry; workingSliceGeometry = m_WorkingSlice->GetGeometry(); itk::Index<2> indexInWorkingSlice2D; indexInWorkingSlice2D[0] = m_SeedPoint[0]; indexInWorkingSlice2D[1] = m_SeedPoint[1]; m_ScreenYDifference += positionEvent->GetPointerPositionOnScreen()[1] - m_LastScreenPosition[1]; m_ScreenXDifference += positionEvent->GetPointerPositionOnScreen()[0] - m_LastScreenPosition[0]; m_LastScreenPosition = Point2I(positionEvent->GetPointerPositionOnScreen()); // Moving the mouse up and down adjusts the width of the threshold window, // moving it left and right shifts the threshold window m_Thresholds[0] = std::min(m_SeedValue, m_InitialThresholds[0] - (m_ScreenYDifference - m_ScreenXDifference) * m_MouseDistanceScaleFactor); m_Thresholds[1] = std::max(m_SeedValue, m_InitialThresholds[1] + (m_ScreenYDifference + m_ScreenXDifference) * m_MouseDistanceScaleFactor); // Do not exceed the pixel type extrema of the reference slice, though m_Thresholds[0] = std::max(m_ThresholdExtrema[0], m_Thresholds[0]); m_Thresholds[1] = std::min(m_ThresholdExtrema[1], m_Thresholds[1]); // Perform region growing again and show the result mitk::Image::Pointer resultImage = mitk::Image::New(); AccessFixedDimensionByItk_3( m_ReferenceSlice, StartRegionGrowing, 2, indexInWorkingSlice2D, m_Thresholds, resultImage); resultImage->SetGeometry(workingSliceGeometry); // Update the contour if (resultImage.IsNotNull() && m_ConnectedComponentValue >= 1) { float isoOffset = 0.33; mitk::ImageToContourModelFilter::Pointer contourExtractor = mitk::ImageToContourModelFilter::New(); contourExtractor->SetInput(resultImage); contourExtractor->SetContourValue(m_ConnectedComponentValue - isoOffset); contourExtractor->Update(); ContourModel::Pointer resultContour = ContourModel::New(); resultContour = contourExtractor->GetOutput(); // Show contour if (resultContour.IsNotNull()) { ContourModel::Pointer resultContourWorld = FeedbackContourTool::BackProjectContourFrom2DSlice( workingSliceGeometry, FeedbackContourTool::ProjectContourTo2DSlice(m_WorkingSlice, resultContour)); FeedbackContourTool::UpdateCurrentFeedbackContour(resultContourWorld); FeedbackContourTool::SetFeedbackContourVisible(true); mitk::RenderingManager::GetInstance()->ForceImmediateUpdate(positionEvent->GetSender()->GetRenderWindow()); } } } } void mitk::RegionGrowingTool::OnMouseReleased(StateMachineAction *, InteractionEvent *interactionEvent) { - // Until OnMousePressedInside() implements a behaviour, we're just returning here whenever m_PaintingPixelValue is 0, - // i.e. when the user clicked inside the segmentation - if (m_PaintingPixelValue == 0) - { - return; - } auto *positionEvent = dynamic_cast(interactionEvent); if (m_WorkingSlice.IsNotNull() && m_FillFeedbackContour && positionEvent) { this->WriteBackFeedbackContourAsSegmentationResult(positionEvent, m_PaintingPixelValue); m_ScreenYDifference = 0; m_ScreenXDifference = 0; } } diff --git a/Modules/Segmentation/Interactions/mitkRegionGrowingTool.h b/Modules/Segmentation/Interactions/mitkRegionGrowingTool.h index 6ba9999718..314c52cd89 100644 --- a/Modules/Segmentation/Interactions/mitkRegionGrowingTool.h +++ b/Modules/Segmentation/Interactions/mitkRegionGrowingTool.h @@ -1,160 +1,138 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef mitkRegionGrowingTool_h_Included #define mitkRegionGrowingTool_h_Included #include "mitkFeedbackContourTool.h" #include #include namespace us { class ModuleResource; } namespace mitk { /** \brief A slice based region growing tool. \sa FeedbackContourTool \ingroup Interaction \ingroup ToolManagerEtAl When the user presses the mouse button, RegionGrowingTool will use the gray values at that position to initialize a region growing algorithm (in the affected 2D slice). By moving the mouse up and down while the button is still pressed, the user can widen or narrow the threshold window, i.e. select more or less within the desired region. The current result of region growing will always be shown as a contour to the user. After releasing the button, the current result of the region growing algorithm will be written to the working image of this tool's ToolManager. - If the first click is inside a segmentation, nothing will happen (other behaviour, for example removal of a - region, can be implemented via OnMousePressedInside()). - \warning Only to be instantiated by mitk::ToolManager. $Author$ */ class MITKSEGMENTATION_EXPORT RegionGrowingTool : public FeedbackContourTool { public: mitkClassMacro(RegionGrowingTool, FeedbackContourTool); itkFactorylessNewMacro(Self); itkCloneMacro(Self); const char **GetXPM() const override; us::ModuleResource GetCursorIconResource() const override; us::ModuleResource GetIconResource() const override; const char *GetName() const override; protected: RegionGrowingTool(); // purposely hidden ~RegionGrowingTool() override; void ConnectActionsAndFunctions() override; void Activated() override; void Deactivated() override; /** * @brief OnMousePressed is called when the user clicks. - * Calls either OnMousePressedInside() or OnMousePressedOutside(). + * Grows a region by calling 'GetNeighborhoodAverage' and 'StartRegionGrowing'. */ virtual void OnMousePressed(StateMachineAction *, InteractionEvent *interactionEvent); - /** - * @brief OnMousePressedInside can be used to implement behaviour when the user clicks inside a segmentation. - */ - virtual void OnMousePressedInside(); - - /** - * @brief OnMousePressedOutside is called when the user clicks outside of the segmented area. - * Grows a region. - */ - virtual void OnMousePressedOutside(StateMachineAction *, InteractionEvent *interactionEvent); - /** * @brief 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. */ virtual void OnMouseMoved(StateMachineAction *, InteractionEvent *interactionEvent); /** * @brief OnMouseReleased converts the feedback contour to a segmentation. */ virtual void OnMouseReleased(StateMachineAction *, InteractionEvent *interactionEvent); /** * @brief Template to calculate average pixel value around index using a square/cube with radius neighborhood. * Example: 1 = 3x3 pixels, 2 = 5x5 pixels, etc. */ template void GetNeighborhoodAverage(const itk::Image *itkImage, const itk::Index& index, ScalarType *result, unsigned int neighborhood = 1); - /** - * @brief Template to check whether index is inside already segmented area. - */ - template - void IsInsideSegmentation(const itk::Image *itkImage, - const itk::Index& index, - bool *result); - /** * @brief Template that calls an ITK filter to do the region growing. */ template void StartRegionGrowing(const itk::Image *itkImage, const itk::Index& seedPoint, const std::array& thresholds, mitk::Image::Pointer &outputImage); /** * @brief Template to calculate the initial thresholds for region growing. */ template void CalculateInitialThresholds(const itk::Image* itkImage); Image::Pointer m_ReferenceSlice; Image::Pointer m_WorkingSlice; ScalarType m_SeedValue; itk::Index<3> m_SeedPoint; std::array m_ThresholdExtrema; std::array m_Thresholds; std::array m_InitialThresholds; Point2I m_LastScreenPosition; int m_ScreenYDifference; int m_ScreenXDifference; private: ScalarType m_MouseDistanceScaleFactor; int m_PaintingPixelValue; bool m_FillFeedbackContour; int m_ConnectedComponentValue; }; } // namespace #endif