A slice based region growing tool. More...
#include <mitkRegionGrowingTool.h>
Public Types | |
typedef RegionGrowingTool | Self |
typedef FeedbackContourTool | Superclass |
typedef itk::SmartPointer< Self > | Pointer |
typedef itk::SmartPointer < const Self > | ConstPointer |
Public Member Functions | |
virtual const char * | GetClassName () const |
virtual const char ** | GetXPM () const |
Returns an icon in the XPM format. | |
virtual const char * | GetName () const |
Returns the name of this tool. Make it short! | |
Static Public Member Functions | |
static Pointer | New () |
Protected Member Functions | |
RegionGrowingTool () | |
virtual | ~RegionGrowingTool () |
virtual void | Activated () |
Called when the tool gets activated (registered to mitk::GlobalInteraction). | |
virtual void | Deactivated () |
Called when the tool gets deactivated (unregistered from mitk::GlobalInteraction). | |
virtual bool | OnMousePressed (Action *, const StateEvent *) |
virtual bool | OnMousePressedInside (Action *, const StateEvent *, mitkIpPicDescriptor *workingPicSlice, int initialWorkingOffset) |
virtual bool | OnMousePressedOutside (Action *, const StateEvent *) |
virtual bool | OnMouseMoved (Action *, const StateEvent *) |
virtual bool | OnMouseReleased (Action *, const StateEvent *) |
mitkIpPicDescriptor * | PerformRegionGrowingAndUpdateContour () |
Protected Attributes | |
Image::Pointer | m_ReferenceSlice |
Image::Pointer | m_WorkingSlice |
int | m_LowerThreshold |
int | m_UpperThreshold |
int | m_InitialLowerThreshold |
int | m_InitialUpperThreshold |
Point2I | m_LastScreenPosition |
int | m_ScreenYDifference |
A slice based region growing tool.
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 change the parameters of the region growing algorithm (selecting more or less of an object). 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 that was generated by region growing (recently), the tool will try to cut off a part of the segmentation. For this reason a skeletonization of the segmentation is generated and the optimal cut point is determined.
$Author$
Definition at line 55 of file mitkRegionGrowingTool.h.
typedef itk::SmartPointer<const Self> mitk::RegionGrowingTool::ConstPointer |
Reimplemented from mitk::FeedbackContourTool.
Definition at line 59 of file mitkRegionGrowingTool.h.
typedef itk::SmartPointer<Self> mitk::RegionGrowingTool::Pointer |
Reimplemented from mitk::FeedbackContourTool.
Definition at line 59 of file mitkRegionGrowingTool.h.
Reimplemented from mitk::FeedbackContourTool.
Definition at line 59 of file mitkRegionGrowingTool.h.
Reimplemented from mitk::FeedbackContourTool.
Definition at line 59 of file mitkRegionGrowingTool.h.
mitk::RegionGrowingTool::RegionGrowingTool | ( | ) | [protected] |
Definition at line 36 of file mitkRegionGrowingTool.cpp.
:FeedbackContourTool("PressMoveRelease"), m_LowerThreshold(200), m_UpperThreshold(200), m_InitialLowerThreshold(200), m_InitialUpperThreshold(200), m_ScreenYDifference(0), m_OriginalPicSlice(NULL), m_SeedPointMemoryOffset(0), m_VisibleWindow(0), m_DefaultWindow(0), m_MouseDistanceScaleFactor(3.0), m_LastWorkingSeed(-1), m_FillFeedbackContour(true) { }
mitk::RegionGrowingTool::~RegionGrowingTool | ( | ) | [protected, virtual] |
Definition at line 53 of file mitkRegionGrowingTool.cpp.
{ }
void mitk::RegionGrowingTool::Activated | ( | ) | [protected, virtual] |
Called when the tool gets activated (registered to mitk::GlobalInteraction).
Derived tools should call their parents implementation.
Reimplemented from mitk::Tool.
Definition at line 67 of file mitkRegionGrowingTool.cpp.
{ Superclass::Activated(); }
void mitk::RegionGrowingTool::Deactivated | ( | ) | [protected, virtual] |
Called when the tool gets deactivated (unregistered from mitk::GlobalInteraction).
Derived tools should call their parents implementation.
Reimplemented from mitk::Tool.
Definition at line 72 of file mitkRegionGrowingTool.cpp.
{ Superclass::Deactivated(); }
virtual const char* mitk::RegionGrowingTool::GetClassName | ( | ) | const [virtual] |
Reimplemented from mitk::FeedbackContourTool.
const char * mitk::RegionGrowingTool::GetName | ( | ) | const [virtual] |
Returns the name of this tool. Make it short!
This name has to fit into some kind of button in most applications, so take some time to think of a good name!
Implements mitk::Tool.
Definition at line 62 of file mitkRegionGrowingTool.cpp.
{ return "Region Growing"; }
const char ** mitk::RegionGrowingTool::GetXPM | ( | ) | const [virtual] |
Returns an icon in the XPM format.
This icon has to fit into some kind of button in most applications, so make it smaller than 25x25 pixels.
XPM is e.g. supported by The Gimp. But if you open any XPM file in your text editor, you will see that you could also "draw" it with an editor.
Implements mitk::Tool.
Definition at line 57 of file mitkRegionGrowingTool.cpp.
{
return mitkRegionGrowingTool_xpm;
}
static Pointer mitk::RegionGrowingTool::New | ( | ) | [static] |
bool mitk::RegionGrowingTool::OnMouseMoved | ( | Action * | action, |
const StateEvent * | stateEvent | ||
) | [protected, virtual] |
If in region growing mode (m_ReferenceSlice != NULL), then 1. Calculate the new thresholds from mouse position (relative to first position) 2. Perform a new region growing and update the feedback contour
Reimplemented from mitk::SegTool2D.
Definition at line 327 of file mitkRegionGrowingTool.cpp.
References mitk::RenderingManager::ForceImmediateUpdate(), mitk::ApplicationCursor::GetCursorPosition(), mitk::StateEvent::GetEvent(), mitk::RenderingManager::GetInstance(), mitk::ApplicationCursor::GetInstance(), mitk::BaseRenderer::GetRenderWindow(), mitk::Event::GetSender(), ipMITKSegmentationFree(), mitkIpPicDescriptor, mitk::SegTool2D::OnMouseMoved(), and mitk::ApplicationCursor::SetCursorPosition().
{ if (FeedbackContourTool::OnMouseMoved( action, stateEvent )) { if ( m_ReferenceSlice.IsNotNull() && m_OriginalPicSlice ) { const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent()); if (positionEvent) { ApplicationCursor* cursor = ApplicationCursor::GetInstance(); if (!cursor) return false; m_ScreenYDifference += cursor->GetCursorPosition()[1] - m_LastScreenPosition[1]; cursor->SetCursorPosition( m_LastScreenPosition ); m_LowerThreshold = m_InitialLowerThreshold + static_cast<int>( m_ScreenYDifference * m_MouseDistanceScaleFactor ); if (m_LowerThreshold < 1) m_LowerThreshold = 1; if (m_LowerThreshold > m_VisibleWindow / 2) m_LowerThreshold = m_VisibleWindow / 2; m_UpperThreshold = m_InitialUpperThreshold + static_cast<int>( m_ScreenYDifference * m_MouseDistanceScaleFactor ); if (m_UpperThreshold < 1) m_UpperThreshold = 1; if (m_UpperThreshold > m_VisibleWindow / 2) m_UpperThreshold = m_VisibleWindow / 2; //MITK_INFO << "new interval: l " << m_LowerThreshold << " u " << m_UpperThreshold << std::endl; // 2. Perform region growing again and show the result mitkIpPicDescriptor* result = PerformRegionGrowingAndUpdateContour(); ipMITKSegmentationFree( result ); // 3. Update the contour mitk::RenderingManager::GetInstance()->ForceImmediateUpdate(positionEvent->GetSender()->GetRenderWindow()); } } } return true; }
bool mitk::RegionGrowingTool::OnMousePressed | ( | Action * | action, |
const StateEvent * | stateEvent | ||
) | [protected, virtual] |
1 Determine which slice is clicked into 2 Determine if the user clicked inside or outside of the segmentation 3 Depending on the pixel value under the mouse click position, two different things happen: (separated out into OnMousePressedInside and OnMousePressedOutside) 3.1 Create a skeletonization of the segmentation and try to find a nice cut 3.1.1 Call a ipSegmentation algorithm to create a nice cut 3.1.2 Set the result of this algorithm as the feedback contour 3.2 Initialize region growing 3.2.1 Determine memory offset inside the original image 3.2.2 Determine initial region growing parameters from the level window settings of the image 3.2.3 Perform a region growing (which generates a new feedback contour)
Reimplemented from mitk::SegTool2D.
Definition at line 89 of file mitkRegionGrowingTool.cpp.
References mitk::CastToItkImage(), mitk::CastToMitkImage(), mitk::SegTool2D::GetAffectedReferenceSlice(), mitk::SegTool2D::GetAffectedWorkingSlice(), mitk::StateEvent::GetEvent(), mitk::DisplayPositionEvent::GetWorldPosition(), ipMITKSegmentationTYPE, mitk::Geometry3D::IsIndexInside(), MITK_INFO, mitkIpPicDescriptor, mitk::Image::New(), mitk::SegTool2D::OnMousePressed(), and mitk::Geometry3D::WorldToIndex().
{ //ToolLogger::SetVerboseness(3); MITK_INFO << "OnMousePressed" << std::endl; if (FeedbackContourTool::OnMousePressed( action, stateEvent )) { MITK_INFO << "OnMousePressed: FeedbackContourTool says ok" << std::endl; // 1. Find out which slice the user clicked, find out which slice of the toolmanager's reference and working image corresponds to that const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent()); if (positionEvent) { MITK_INFO << "OnMousePressed: got positionEvent" << std::endl; m_ReferenceSlice = FeedbackContourTool::GetAffectedReferenceSlice( positionEvent ); m_WorkingSlice = FeedbackContourTool::GetAffectedWorkingSlice( positionEvent ); if ( m_WorkingSlice.IsNotNull() ) // can't do anything without the segmentation { MITK_INFO << "OnMousePressed: got working slice" << std::endl; // 2. Determine if the user clicked inside or outside of the segmentation const Geometry3D* workingSliceGeometry = m_WorkingSlice->GetGeometry(); Point3D mprojectedPointIn2D; workingSliceGeometry->WorldToIndex( positionEvent->GetWorldPosition(), mprojectedPointIn2D); itk::Index<2> projectedPointInWorkingSlice2D; projectedPointInWorkingSlice2D[0] = static_cast<int>( mprojectedPointIn2D[0] - 0.5 ); projectedPointInWorkingSlice2D[1] = static_cast<int>( mprojectedPointIn2D[1] - 0.5 ); if ( workingSliceGeometry->IsIndexInside( projectedPointInWorkingSlice2D ) ) { MITK_INFO << "OnMousePressed: point " << positionEvent->GetWorldPosition() << " (index coordinates " << projectedPointInWorkingSlice2D << ") IS in working slice" << std::endl; // Convert to ipMITKSegmentationTYPE (because getting pixels relys on that data type) itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer correctPixelTypeImage; CastToItkImage( m_WorkingSlice, correctPixelTypeImage ); assert (correctPixelTypeImage.IsNotNull() ); // possible bug in CastToItkImage ? // direction maxtrix is wrong/broken/not working after CastToItkImage, leading to a failed assertion in // mitk/Core/DataStructures/mitkSlicedGeometry3D.cpp, 479: // virtual void mitk::SlicedGeometry3D::SetSpacing(const mitk::Vector3D&): Assertion `aSpacing[0]>0 && aSpacing[1]>0 && aSpacing[2]>0' failed // solution here: we overwrite it with an unity matrix itk::Image< ipMITKSegmentationTYPE, 2 >::DirectionType imageDirection; imageDirection.SetIdentity(); correctPixelTypeImage->SetDirection(imageDirection); Image::Pointer temporarySlice = Image::New(); // temporarySlice = ImportItkImage( correctPixelTypeImage ); CastToMitkImage( correctPixelTypeImage, temporarySlice ); mitkIpPicDescriptor* workingPicSlice = temporarySlice->GetSliceData()->GetPicDescriptor(); int initialWorkingOffset = projectedPointInWorkingSlice2D[1] * workingPicSlice->n[0] + projectedPointInWorkingSlice2D[0]; if ( initialWorkingOffset < static_cast<int>( workingPicSlice->n[0] * workingPicSlice->n[1] ) && initialWorkingOffset >= 0 ) { // 3. determine the pixel value under the last click bool inside = static_cast<ipMITKSegmentationTYPE*>(workingPicSlice->data)[initialWorkingOffset] != 0; m_PaintingPixelValue = inside ? 0 : 1; // if inside, we want to remove a part, otherwise we want to add something if ( m_LastWorkingSeed >= static_cast<int>( workingPicSlice->n[0] * workingPicSlice->n[1] ) || m_LastWorkingSeed < 0 ) { inside = false; } if ( m_ReferenceSlice.IsNotNull() ) { MITK_INFO << "OnMousePressed: got reference slice" << std::endl; m_OriginalPicSlice = m_ReferenceSlice->GetSliceData()->GetPicDescriptor(); // 3.1. Switch depending on the pixel value if (inside) { OnMousePressedInside(action, stateEvent, workingPicSlice, initialWorkingOffset); } else { OnMousePressedOutside(action, stateEvent); } } } } } } } MITK_INFO << "end OnMousePressed" << std::endl; return true; }
bool mitk::RegionGrowingTool::OnMousePressedInside | ( | Action * | , |
const StateEvent * | stateEvent, | ||
mitkIpPicDescriptor * | workingPicSlice, | ||
int | initialWorkingOffset | ||
) | [protected, virtual] |
3.1 Create a skeletonization of the segmentation and try to find a nice cut 3.1.1 Call a ipSegmentation algorithm to create a nice cut 3.1.2 Set the result of this algorithm as the feedback contour
Definition at line 189 of file mitkRegionGrowingTool.cpp.
References mitk::FeedbackContourTool::BackProjectContourFrom2DSlice(), tCutResult::cutIt, tCutResult::deleteCurve, tCutResult::deleteSize, mitk::StateEvent::GetEvent(), mitk::RenderingManager::GetInstance(), mitk::BaseRenderer::GetRenderWindow(), mitk::Event::GetSender(), ipMITKSegmentationCreateGrowerHistory(), ipMITKSegmentationGetCutPoints(), mitkIpPicDescriptor, mitk::Contour::New(), tCutResult::onGradient, mitk::RenderingManager::RequestUpdate(), mitk::FeedbackContourTool::SetFeedbackContour(), mitk::FeedbackContourTool::SetFeedbackContourVisible(), and tCutResult::traceline.
{ const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent()); // checked in OnMousePressed // 3.1.1. Create a skeletonization of the segmentation and try to find a nice cut // apply the skeletonization-and-cut algorithm // generate contour to remove // set m_ReferenceSlice = NULL so nothing will happen during mouse move // remember to fill the contour with 0 in mouserelease mitkIpPicDescriptor* segmentationHistory = ipMITKSegmentationCreateGrowerHistory( workingPicSlice, m_LastWorkingSeed, NULL ); // free again if (segmentationHistory) { tCutResult cutContour = ipMITKSegmentationGetCutPoints( workingPicSlice, segmentationHistory, initialWorkingOffset ); // tCutResult is a ipSegmentation type mitkIpPicFree( segmentationHistory ); if (cutContour.cutIt) { // 3.1.2 copy point from float* to mitk::Contour Contour::Pointer contourInImageIndexCoordinates = Contour::New(); contourInImageIndexCoordinates->Initialize(); Point3D newPoint; for (int index = 0; index < cutContour.deleteSize; ++index) { newPoint[0] = cutContour.deleteCurve[ 2 * index + 0 ]; newPoint[1] = cutContour.deleteCurve[ 2 * index + 1]; newPoint[2] = 0.0; contourInImageIndexCoordinates->AddVertex( newPoint + 0.5 ); } free(cutContour.traceline); free(cutContour.deleteCurve); // perhaps visualize this for fun? free(cutContour.onGradient); Contour::Pointer contourInWorldCoordinates = FeedbackContourTool::BackProjectContourFrom2DSlice( m_WorkingSlice, contourInImageIndexCoordinates, true ); // true: sub 0.5 for ipSegmentation correction FeedbackContourTool::SetFeedbackContour( *contourInWorldCoordinates ); FeedbackContourTool::SetFeedbackContourVisible(true); mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() ); m_FillFeedbackContour = true; } else { m_FillFeedbackContour = false; } } else { m_FillFeedbackContour = false; } m_ReferenceSlice = NULL; return true; }
bool mitk::RegionGrowingTool::OnMousePressedOutside | ( | Action * | , |
const StateEvent * | stateEvent | ||
) | [protected, virtual] |
3.2 Initialize region growing 3.2.1 Determine memory offset inside the original image 3.2.2 Determine initial region growing parameters from the level window settings of the image 3.2.3 Perform a region growing (which generates a new feedback contour)
Definition at line 250 of file mitkRegionGrowingTool.cpp.
References mitk::ApplicationCursor::GetCursorPosition(), mitk::LevelWindow::GetDefaultWindow(), mitk::BaseRenderer::GetDisplayGeometry(), mitk::DisplayGeometry::GetDisplayHeight(), mitk::StateEvent::GetEvent(), mitk::RenderingManager::GetInstance(), mitk::ApplicationCursor::GetInstance(), mitk::BaseRenderer::GetRenderWindow(), mitk::Event::GetSender(), mitk::LevelWindow::GetWindow(), mitk::DisplayPositionEvent::GetWorldPosition(), ipMITKSegmentationFree(), mitk::Geometry3D::IsIndexInside(), MITK_INFO, mitkIpPicDescriptor, mitk::RenderingManager::RequestUpdate(), mitk::FeedbackContourTool::SetFeedbackContourVisible(), and mitk::Geometry3D::WorldToIndex().
{ const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent()); // checked in OnMousePressed // 3.2 If we have a reference image, then perform an initial region growing, considering the reference image's level window // if click was outside the image, don't continue const Geometry3D* sliceGeometry = m_ReferenceSlice->GetGeometry(); Point3D mprojectedPointIn2D; sliceGeometry->WorldToIndex( positionEvent->GetWorldPosition(), mprojectedPointIn2D ); itk::Index<2> projectedPointIn2D; projectedPointIn2D[0] = static_cast<int>( mprojectedPointIn2D[0] - 0.5 ); projectedPointIn2D[1] = static_cast<int>( mprojectedPointIn2D[1] - 0.5 ); if ( sliceGeometry->IsIndexInside( mprojectedPointIn2D ) ) { MITK_INFO << "OnMousePressed: point " << positionEvent->GetWorldPosition() << " (index coordinates " << mprojectedPointIn2D << ") IS in reference slice" << std::endl; // 3.2.1 Remember Y cursor position and initial seed point //m_ScreenYPositionAtStart = static_cast<int>(positionEvent->GetDisplayPosition()[1]); m_LastScreenPosition = ApplicationCursor::GetInstance()->GetCursorPosition(); m_ScreenYDifference = 0; m_SeedPointMemoryOffset = projectedPointIn2D[1] * m_OriginalPicSlice->n[0] + projectedPointIn2D[0]; m_LastWorkingSeed = m_SeedPointMemoryOffset; // remember for skeletonization if ( m_SeedPointMemoryOffset < static_cast<int>( m_OriginalPicSlice->n[0] * m_OriginalPicSlice->n[1] ) && m_SeedPointMemoryOffset >= 0 ) { // 3.2.2 Get level window from reference DataNode // Use some logic to determine initial gray value bounds LevelWindow lw(0, 500); m_ToolManager->GetReferenceData(0)->GetLevelWindow(lw); // will fill lw if levelwindow property is present, otherwise won't touch it. m_VisibleWindow = lw.GetWindow(); // necessary for limiting the upper and lower threshold to the maximum gray values m_DefaultWindow = lw.GetDefaultWindow(); static bool initializedAlready = false; // just evaluated once if (!initializedAlready) { m_InitialLowerThreshold = static_cast<int>(m_VisibleWindow / 10.0); // 20% of the visible gray values m_InitialUpperThreshold = static_cast<int>(m_VisibleWindow / 10.0); initializedAlready = true; } m_LowerThreshold = m_InitialLowerThreshold; m_UpperThreshold = m_InitialUpperThreshold; DisplayGeometry* displayGeometry = positionEvent->GetSender()->GetDisplayGeometry(); if (displayGeometry) { m_MouseDistanceScaleFactor = m_VisibleWindow / ( 3.0 * displayGeometry->GetDisplayHeight() ); } // 3.2.3. Actually perform region growing mitkIpPicDescriptor* result = PerformRegionGrowingAndUpdateContour(); ipMITKSegmentationFree( result); // display the contour FeedbackContourTool::SetFeedbackContourVisible(true); mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow()); m_FillFeedbackContour = true; } } return true; }
bool mitk::RegionGrowingTool::OnMouseReleased | ( | Action * | action, |
const StateEvent * | stateEvent | ||
) | [protected, virtual] |
If the feedback contour should be filled, then it is done here. (Contour is NOT filled, when skeletonization is done but no nice cut was found)
Reimplemented from mitk::SegTool2D.
Definition at line 367 of file mitkRegionGrowingTool.cpp.
References mitk::SegTool2D::DetermineAffectedImageSlice(), mitk::FeedbackContourTool::FillContourInSlice(), mitk::BaseRenderer::GetCurrentWorldGeometry2D(), mitk::StateEvent::GetEvent(), mitk::FeedbackContourTool::GetFeedbackContour(), mitk::RenderingManager::GetInstance(), mitk::BaseRenderer::GetRenderWindow(), mitk::Event::GetSender(), mitk::BaseRenderer::GetTimeStep(), MITK_INFO, mitk::OverwriteSliceImageFilter::New(), mitk::SegTool2D::OnMouseReleased(), mitk::FeedbackContourTool::ProjectContourTo2DSlice(), mitk::RenderingManager::RequestUpdate(), and mitk::FeedbackContourTool::SetFeedbackContourVisible().
{ if (FeedbackContourTool::OnMouseReleased( action, stateEvent )) { // 1. If we have a working slice, use the contour to fill a new piece on segmentation on it (or erase a piece that was selected by ipMITKSegmentationGetCutPoints) if ( m_WorkingSlice.IsNotNull() && m_OriginalPicSlice ) { const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent()); if (positionEvent) { // remember parameters for next time m_InitialLowerThreshold = m_LowerThreshold; m_InitialUpperThreshold = m_UpperThreshold; if (m_FillFeedbackContour) { // 3. use contour to fill a region in our working slice Contour* feedbackContour( FeedbackContourTool::GetFeedbackContour() ); if (feedbackContour) { Contour::Pointer projectedContour = FeedbackContourTool::ProjectContourTo2DSlice( m_WorkingSlice, feedbackContour, false, false ); // false: don't add any 0.5 // false: don't constrain the contour to the image's inside if (projectedContour.IsNotNull()) { FeedbackContourTool::FillContourInSlice( projectedContour, m_WorkingSlice, m_PaintingPixelValue ); // 4. write working slice back into image volume int affectedDimension( -1 ); int affectedSlice( -1 ); const PlaneGeometry* planeGeometry( dynamic_cast<const PlaneGeometry*> (positionEvent->GetSender()->GetCurrentWorldGeometry2D() ) ); FeedbackContourTool::DetermineAffectedImageSlice( dynamic_cast<Image*>( m_ToolManager->GetWorkingData(0)->GetData() ), planeGeometry, affectedDimension, affectedSlice ); MITK_INFO << "OnMouseReleased: writing back to dimension " << affectedDimension << ", slice " << affectedSlice << " in working image" << std::endl; OverwriteSliceImageFilter::Pointer slicewriter = OverwriteSliceImageFilter::New(); Image::Pointer workingImage = dynamic_cast<Image*>( m_ToolManager->GetWorkingData(0)->GetData() ); slicewriter->SetInput( workingImage ); slicewriter->SetCreateUndoInformation( true ); slicewriter->SetSliceImage( m_WorkingSlice ); slicewriter->SetSliceDimension( affectedDimension ); slicewriter->SetSliceIndex( affectedSlice ); slicewriter->SetTimeStep( positionEvent->GetSender()->GetTimeStep( workingImage ) ); slicewriter->Update(); } } } FeedbackContourTool::SetFeedbackContourVisible(false); mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() ); } } } m_ReferenceSlice = NULL; // don't leak m_WorkingSlice = NULL; m_OriginalPicSlice = NULL; return true; }
mitkIpPicDescriptor * mitk::RegionGrowingTool::PerformRegionGrowingAndUpdateContour | ( | ) | [protected] |
Uses ipSegmentation algorithms to do the actual region growing. The result (binary image) is first smoothed by a 5x5 circle mask, then its contour is extracted and converted to MITK coordinates.
Definition at line 431 of file mitkRegionGrowingTool.cpp.
References mitk::FeedbackContourTool::BackProjectContourFrom2DSlice(), ipMITKSegmentationFree(), ipMITKSegmentationGetContour8N(), ipMITKSegmentationGrowRegion4N(), ipMITKSegmentationIsInsideContour(), ipMITKSegmentationReplaceRegion4N(), mitkIpPicDescriptor, mitk::Contour::New(), and mitk::FeedbackContourTool::SetFeedbackContour().
{ // 1. m_OriginalPicSlice and m_SeedPointMemoryOffset are set to sensitive values, as well as m_LowerThreshold and m_UpperThreshold assert (m_OriginalPicSlice); if (m_OriginalPicSlice->n[0] != 256 || m_OriginalPicSlice->n[1] != 256) // ??? assert( (m_SeedPointMemoryOffset < static_cast<int>( m_OriginalPicSlice->n[0] * m_OriginalPicSlice->n[1] )) && (m_SeedPointMemoryOffset >= 0) ); // inside the image // 2. ipSegmentation is used to perform region growing float ignored; int oneContourOffset( 0 ); mitkIpPicDescriptor* regionGrowerResult = ipMITKSegmentationGrowRegion4N( m_OriginalPicSlice, m_SeedPointMemoryOffset, // seed point true, // grayvalue interval relative to seed point gray value? m_LowerThreshold, m_UpperThreshold, 0, // continue until done (maxIterations == 0) NULL, // allocate new memory (only this time, on mouse move we'll reuse the old buffer) oneContourOffset, // a pixel that is near the resulting contour ignored // ignored by us ); if (!regionGrowerResult || oneContourOffset == -1) { Contour::Pointer dummyContour = Contour::New(); dummyContour->Initialize(); FeedbackContourTool::SetFeedbackContour( *dummyContour ); if (regionGrowerResult) ipMITKSegmentationFree(regionGrowerResult); return NULL; } // 3. We smooth the result a little to reduce contour complexity bool smoothResult( true ); // currently fixed, perhaps remove else block mitkIpPicDescriptor* smoothedRegionGrowerResult; if (smoothResult) { // Smooth the result (otherwise very detailed contour) smoothedRegionGrowerResult = SmoothIPPicBinaryImage( regionGrowerResult, oneContourOffset ); ipMITKSegmentationFree( regionGrowerResult ); } else { smoothedRegionGrowerResult = regionGrowerResult; } // 4. convert the result of region growing into a mitk::Contour // At this point oneContourOffset could be useless, if smoothing destroyed a thin bridge. In these // cases, we have two or more unconnected segmentation regions, and we don't know, which one is touched by oneContourOffset. // In the bad case, the contour is not the one around our seedpoint, so the result looks very strange to the user. // -> we remove the point where the contour started so far. Then we look from the bottom of the image for the first segmentation pixel // and start another contour extraction from there. This is done, until the seedpoint is inside the contour int numberOfContourPoints( 0 ); int newBufferSize( 0 ); float* contourPoints = ipMITKSegmentationGetContour8N( smoothedRegionGrowerResult, oneContourOffset, numberOfContourPoints, newBufferSize ); // memory allocated with malloc if (contourPoints) { while ( !ipMITKSegmentationIsInsideContour( contourPoints, // contour numberOfContourPoints, // points in contour m_SeedPointMemoryOffset % smoothedRegionGrowerResult->n[0], // test point x m_SeedPointMemoryOffset / smoothedRegionGrowerResult->n[0] // test point y ) ) { // we decide that this cannot be part of the segmentation because the seedpoint is not contained in the contour (fill the 4-neighborhood with 0) ipMITKSegmentationReplaceRegion4N( smoothedRegionGrowerResult, oneContourOffset, 0 ); // move the contour offset to the last row (x position of the seed point) int rowLength = smoothedRegionGrowerResult->n[0]; // number of pixels in a row oneContourOffset = m_SeedPointMemoryOffset % smoothedRegionGrowerResult->n[0] // x of seed point + rowLength*(smoothedRegionGrowerResult->n[1]-1); // y of last row while ( oneContourOffset >=0 && (*(static_cast<ipMITKSegmentationTYPE*>(smoothedRegionGrowerResult->data) + oneContourOffset) == 0) ) { oneContourOffset -= rowLength; // if pixel at data+oneContourOffset is 0, then move up one row } if ( oneContourOffset < 0 ) { break; // just use the last contour we found } free(contourPoints); // release contour memory contourPoints = ipMITKSegmentationGetContour8N( smoothedRegionGrowerResult, oneContourOffset, numberOfContourPoints, newBufferSize ); // memory allocated with malloc } // copy point from float* to mitk::Contour Contour::Pointer contourInImageIndexCoordinates = Contour::New(); contourInImageIndexCoordinates->Initialize(); Point3D newPoint; for (int index = 0; index < numberOfContourPoints; ++index) { newPoint[0] = contourPoints[ 2 * index + 0 ]; newPoint[1] = contourPoints[ 2 * index + 1]; newPoint[2] = 0; contourInImageIndexCoordinates->AddVertex( newPoint ); } free(contourPoints); Contour::Pointer contourInWorldCoordinates = FeedbackContourTool::BackProjectContourFrom2DSlice( m_ReferenceSlice, contourInImageIndexCoordinates, true ); // true: sub 0.5 for ipSegmentation correctio FeedbackContourTool::SetFeedbackContour( *contourInWorldCoordinates ); } // 5. Result HAS TO BE freed by caller, contains the binary region growing result return smoothedRegionGrowerResult; }
int mitk::RegionGrowingTool::m_InitialLowerThreshold [protected] |
Definition at line 86 of file mitkRegionGrowingTool.h.
int mitk::RegionGrowingTool::m_InitialUpperThreshold [protected] |
Definition at line 87 of file mitkRegionGrowingTool.h.
Point2I mitk::RegionGrowingTool::m_LastScreenPosition [protected] |
Definition at line 89 of file mitkRegionGrowingTool.h.
int mitk::RegionGrowingTool::m_LowerThreshold [protected] |
Definition at line 84 of file mitkRegionGrowingTool.h.
Definition at line 81 of file mitkRegionGrowingTool.h.
int mitk::RegionGrowingTool::m_ScreenYDifference [protected] |
Definition at line 90 of file mitkRegionGrowingTool.h.
int mitk::RegionGrowingTool::m_UpperThreshold [protected] |
Definition at line 85 of file mitkRegionGrowingTool.h.
Definition at line 82 of file mitkRegionGrowingTool.h.