Public Types | Public Member Functions | Protected Member Functions | Protected Attributes

mitk::SetRegionTool Class Reference
[Interaction ClassesClasses related to InteractiveSegmentation]

Fills or erases a 2D region. More...

#include <mitkSetRegionTool.h>

Inheritance diagram for mitk::SetRegionTool:
Inheritance graph
[legend]
Collaboration diagram for mitk::SetRegionTool:
Collaboration graph
[legend]

List of all members.

Public Types

typedef SetRegionTool Self
typedef FeedbackContourTool Superclass
typedef itk::SmartPointer< SelfPointer
typedef itk::SmartPointer
< const Self
ConstPointer

Public Member Functions

virtual const char * GetClassName () const

Protected Member Functions

 SetRegionTool (int paintingPixelValue=1)
virtual ~SetRegionTool ()
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 OnMouseReleased (Action *, const StateEvent *)
virtual bool OnInvertLogic (Action *, const StateEvent *)

Protected Attributes

int m_PaintingPixelValue
bool m_FillContour
bool m_StatusFillWholeSlice
Contour::Pointer m_SegmentationContourInWorldCoordinates
Contour::Pointer m_WholeImageContourInWorldCoordinates

Detailed Description

Fills or erases a 2D region.

See also:
FeedbackContourTool
ExtractImageFilter
OverwriteSliceImageFilter

Finds the outer contour of a shape in 2D (possibly including holes) and sets all the inside pixels to a specified value. This might fill holes or erase segmentations.

Warning:
Only to be instantiated by mitk::ToolManager.

$Author$

Definition at line 47 of file mitkSetRegionTool.h.


Member Typedef Documentation

typedef itk::SmartPointer<const Self> mitk::SetRegionTool::ConstPointer

Reimplemented from mitk::FeedbackContourTool.

Reimplemented in mitk::EraseRegionTool, and mitk::FillRegionTool.

Definition at line 51 of file mitkSetRegionTool.h.

typedef itk::SmartPointer<Self> mitk::SetRegionTool::Pointer

Reimplemented from mitk::FeedbackContourTool.

Reimplemented in mitk::EraseRegionTool, and mitk::FillRegionTool.

Definition at line 51 of file mitkSetRegionTool.h.

Reimplemented from mitk::FeedbackContourTool.

Reimplemented in mitk::EraseRegionTool, and mitk::FillRegionTool.

Definition at line 51 of file mitkSetRegionTool.h.

Reimplemented from mitk::FeedbackContourTool.

Reimplemented in mitk::EraseRegionTool, and mitk::FillRegionTool.

Definition at line 51 of file mitkSetRegionTool.h.


Constructor & Destructor Documentation

mitk::SetRegionTool::SetRegionTool ( int  paintingPixelValue = 1 ) [protected]

Definition at line 27 of file mitkSetRegionTool.cpp.

:FeedbackContourTool("PressMoveReleaseWithCTRLInversion"),
 m_PaintingPixelValue(paintingPixelValue),
 m_FillContour(false),
 m_StatusFillWholeSlice(false)
{
}
mitk::SetRegionTool::~SetRegionTool (  ) [protected, virtual]

Definition at line 35 of file mitkSetRegionTool.cpp.

{
}

Member Function Documentation

void mitk::SetRegionTool::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 39 of file mitkSetRegionTool.cpp.

void mitk::SetRegionTool::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 44 of file mitkSetRegionTool.cpp.

virtual const char* mitk::SetRegionTool::GetClassName (  ) const [virtual]

Reimplemented from mitk::FeedbackContourTool.

Reimplemented in mitk::EraseRegionTool, and mitk::FillRegionTool.

bool mitk::SetRegionTool::OnInvertLogic ( Action action,
const StateEvent stateEvent 
) [protected, virtual]

Called when the CTRL key is pressed. Will change the painting pixel value from 0 to 1 or from 1 to 0.

Reimplemented from mitk::SegTool2D.

Definition at line 303 of file mitkSetRegionTool.cpp.

References mitk::StateEvent::GetEvent(), mitk::RenderingManager::GetInstance(), mitk::BaseRenderer::GetRenderWindow(), mitk::Event::GetSender(), mitk::SegTool2D::OnInvertLogic(), mitk::RenderingManager::RequestUpdate(), and mitk::FeedbackContourTool::SetFeedbackContour().

{
  if (!FeedbackContourTool::OnInvertLogic(action, stateEvent)) return false;
  
  const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
  if (!positionEvent) return false;

  if (m_StatusFillWholeSlice)
  {
    // use contour extracted from image data
    if (m_SegmentationContourInWorldCoordinates.IsNotNull())
      FeedbackContourTool::SetFeedbackContour( *m_SegmentationContourInWorldCoordinates );
    mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow());
  } 
  else
  {
    // use some artificial contour
    if (m_WholeImageContourInWorldCoordinates.IsNotNull())
      FeedbackContourTool::SetFeedbackContour( *m_WholeImageContourInWorldCoordinates );
    mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow());
  }

  m_StatusFillWholeSlice = !m_StatusFillWholeSlice;

  return true;
}
bool mitk::SetRegionTool::OnMousePressed ( Action action,
const StateEvent stateEvent 
) [protected, virtual]

The logic of finding a starting point for the contour is the following:

  • If the initial seed point is 0, we are either inside a hole or outside of every segmentation. We move to the right until we hit a 1, which must be part of a contour.
  • If the initial seed point is 1, then ... we now do the same (running to the right) until we hit a 1

In both cases the found contour point is used to extract a contour and then a test is applied to find out if the initial seed point is contained in the contour. If this is the case, filling should be applied, otherwise nothing is done.

Reimplemented from mitk::SegTool2D.

Definition at line 49 of file mitkSetRegionTool.cpp.

References mitk::FeedbackContourTool::BackProjectContourFrom2DSlice(), mitk::CastToItkImage(), mitk::CastToMitkImage(), mitk::SegTool2D::GetAffectedWorkingSlice(), mitk::StateEvent::GetEvent(), mitk::RenderingManager::GetInstance(), mitk::BaseRenderer::GetRenderWindow(), mitk::Event::GetSender(), mitk::DisplayPositionEvent::GetWorldPosition(), ipMITKSegmentationGetContour8N(), ipMITKSegmentationIsInsideContour(), ipMITKSegmentationTYPE, mitk::Geometry3D::IsIndexInside(), MITK_ERROR, mitkIpPicDescriptor, mitk::Contour::New(), mitk::Image::New(), mitk::SegTool2D::OnMousePressed(), mitk::RenderingManager::RequestUpdate(), mitk::FeedbackContourTool::SetFeedbackContour(), mitk::FeedbackContourTool::SetFeedbackContourVisible(), and mitk::Geometry3D::WorldToIndex().

{
  if (!FeedbackContourTool::OnMousePressed( action, stateEvent )) return false;

  const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
  if (!positionEvent) return false;

  // 1. Get the working image
  Image::Pointer workingSlice   = FeedbackContourTool::GetAffectedWorkingSlice( positionEvent );
  if ( workingSlice.IsNull() ) return false; // can't do anything without the segmentation
 
  // if click was outside the image, don't continue
  const Geometry3D* sliceGeometry = workingSlice->GetGeometry();
  itk::Index<2> projectedPointIn2D;
  sliceGeometry->WorldToIndex( positionEvent->GetWorldPosition(), projectedPointIn2D );
  if ( !sliceGeometry->IsIndexInside( projectedPointIn2D ) )
  {
    MITK_ERROR << "point apparently not inside segmentation slice" << std::endl;
    return false; // can't use that as a seed point
  }
  
    // Convert to ipMITKSegmentationTYPE (because ipMITKSegmentationGetContour8N relys on that data type)
    itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer correctPixelTypeImage;
    CastToItkImage( 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 );


  // check index positions
  mitkIpPicDescriptor* originalPicSlice = temporarySlice->GetSliceData()->GetPicDescriptor();
 
  int m_SeedPointMemoryOffset = projectedPointIn2D[1] * originalPicSlice->n[0] + projectedPointIn2D[0];

  if ( m_SeedPointMemoryOffset >= static_cast<int>( originalPicSlice->n[0] * originalPicSlice->n[1] ) ||
       m_SeedPointMemoryOffset < 0 )
  {
    MITK_ERROR << "Memory offset calculation if mitk::SetRegionTool has some serious flaw! Aborting.." << std::endl;
    return false;
  }
  
  // 2. Determine the contour that surronds the selected "piece of the image"
  
  // find a contour seed point
  unsigned int oneContourOffset = static_cast<unsigned int>( m_SeedPointMemoryOffset ); // safe because of earlier check if m_SeedPointMemoryOffset < 0

  unsigned int size = originalPicSlice->n[0] * originalPicSlice->n[1];
/*
  unsigned int rowSize = originalPicSlice->n[0];
*/
  ipMITKSegmentationTYPE* data = static_cast<ipMITKSegmentationTYPE*>(originalPicSlice->data);

  if ( data[oneContourOffset] == 0 ) // initial seed 0
  {
    for ( ; oneContourOffset < size; ++oneContourOffset )
    {
      if ( data[oneContourOffset] > 0 ) break;
    }
  }
  else if ( data[oneContourOffset] == 1 ) // initial seed 1
  {
    unsigned int lastValidPixel = size-1; // initialization, will be changed lateron
    bool inSeg = true;    // inside segmentation?
    for ( ; oneContourOffset < size; ++oneContourOffset )
    {
      if ( ( data[oneContourOffset] == 0 ) && inSeg ) // pixel 0 and inside-flag set: this happens at the first pixel outside a filled region
      {
        inSeg = false;
        lastValidPixel = oneContourOffset - 1; // store the last pixel position inside a filled region
        break;
      }
      else // pixel 1, inside-flag doesn't matter: this happens while we are inside a filled region
      {
        inSeg = true; // first iteration lands here
      }
      
    }
    oneContourOffset = lastValidPixel;
  }
  else
  {
    MITK_ERROR << "Fill/Erase was never intended to work with other than binary images." << std::endl;
    m_FillContour = false;
    return false;
  }

  if (oneContourOffset == size) // nothing found until end of slice
  {
    m_FillContour = false;
    return false;
  }
  
  int numberOfContourPoints( 0 );
  int newBufferSize( 0 );
  //MITK_INFO << "getting contour from offset " << oneContourOffset << " ("<<oneContourOffset%originalPicSlice->n[0]<<","<<oneContourOffset/originalPicSlice->n[0]<<")"<<std::endl;
  float* contourPoints = ipMITKSegmentationGetContour8N( originalPicSlice, oneContourOffset, numberOfContourPoints, newBufferSize ); // memory allocated with malloc
  
  //MITK_INFO << "contourPoints " << contourPoints << " (N="<<numberOfContourPoints<<")"<<std::endl;
  assert(contourPoints == NULL || numberOfContourPoints > 0);
    
  bool cursorInsideContour = ipMITKSegmentationIsInsideContour( contourPoints, numberOfContourPoints, projectedPointIn2D[0], projectedPointIn2D[1]);

  // decide if contour should be filled or not
  m_FillContour = cursorInsideContour;

  if (m_FillContour)
  {
    // 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 );
    }

    m_SegmentationContourInWorldCoordinates = FeedbackContourTool::BackProjectContourFrom2DSlice( workingSlice, contourInImageIndexCoordinates, true ); // true, correct the result from ipMITKSegmentationGetContour8N

    // 3. Show the contour
    FeedbackContourTool::SetFeedbackContour( *m_SegmentationContourInWorldCoordinates );
    
    FeedbackContourTool::SetFeedbackContourVisible(true);
    mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow());
  }

  // always generate a second contour, containing the whole image (used when CTRL is pressed)
  {
    // copy point from float* to mitk::Contour 
    Contour::Pointer contourInImageIndexCoordinates = Contour::New();
    contourInImageIndexCoordinates->Initialize();
    Point3D newPoint;
    newPoint[0] = 0; newPoint[1] = 0; newPoint[2] = 0.0;
    contourInImageIndexCoordinates->AddVertex( newPoint );
    newPoint[0] = originalPicSlice->n[0]; newPoint[1] = 0; newPoint[2] = 0.0;
    contourInImageIndexCoordinates->AddVertex( newPoint );
    newPoint[0] = originalPicSlice->n[0]; newPoint[1] = originalPicSlice->n[1]; newPoint[2] = 0.0;
    contourInImageIndexCoordinates->AddVertex( newPoint );
    newPoint[0] = 0; newPoint[1] = originalPicSlice->n[1]; newPoint[2] = 0.0;
    contourInImageIndexCoordinates->AddVertex( newPoint );

    m_WholeImageContourInWorldCoordinates = FeedbackContourTool::BackProjectContourFrom2DSlice( workingSlice, contourInImageIndexCoordinates, true ); // true, correct the result from ipMITKSegmentationGetContour8N

    // 3. Show the contour
    FeedbackContourTool::SetFeedbackContour( *m_SegmentationContourInWorldCoordinates );
    
    FeedbackContourTool::SetFeedbackContourVisible(true);
    mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow());
  }


  free(contourPoints);

  return true;
}
bool mitk::SetRegionTool::OnMouseReleased ( Action action,
const StateEvent stateEvent 
) [protected, virtual]

Reimplemented from mitk::SegTool2D.

Definition at line 233 of file mitkSetRegionTool.cpp.

References mitk::SegTool2D::DetermineAffectedImageSlice(), mitk::FeedbackContourTool::FillContourInSlice(), mitk::SegTool2D::GetAffectedImageSliceAs2DImage(), mitk::BaseRenderer::GetCurrentWorldGeometry2D(), mitk::StateEvent::GetEvent(), mitk::FeedbackContourTool::GetFeedbackContour(), mitk::RenderingManager::GetInstance(), mitk::BaseRenderer::GetRenderWindow(), mitk::Event::GetSender(), mitk::BaseRenderer::GetTimeStep(), MITK_ERROR, mitk::OverwriteSliceImageFilter::New(), mitk::SegTool2D::OnMouseReleased(), mitk::FeedbackContourTool::ProjectContourTo2DSlice(), mitk::RenderingManager::RequestUpdate(), and mitk::FeedbackContourTool::SetFeedbackContourVisible().

{
  // 1. Hide the feedback contour, find out which slice the user clicked, find out which slice of the toolmanager's working image corresponds to that
  FeedbackContourTool::SetFeedbackContourVisible(false);
  
  const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
  if (!positionEvent) return false;

  assert( positionEvent->GetSender()->GetRenderWindow() );
  mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow());
  
  if (!m_FillContour && !m_StatusFillWholeSlice) return true;
  
  if (!FeedbackContourTool::OnMouseReleased( action, stateEvent )) return false;

  DataNode* workingNode( m_ToolManager->GetWorkingData(0) );
  if (!workingNode) return false;

  Image* image = dynamic_cast<Image*>(workingNode->GetData());
  const PlaneGeometry* planeGeometry( dynamic_cast<const PlaneGeometry*> (positionEvent->GetSender()->GetCurrentWorldGeometry2D() ) );
  if ( !image || !planeGeometry ) return false;

  int affectedDimension( -1 );
  int affectedSlice( -1 );
  if ( FeedbackContourTool::DetermineAffectedImageSlice( image, planeGeometry, affectedDimension, affectedSlice ) )
  {
    // 2. Slice is known, now we try to get it as a 2D image and project the contour into index coordinates of this slice
    Image::Pointer slice = FeedbackContourTool::GetAffectedImageSliceAs2DImage( positionEvent, image );

    if ( slice.IsNull() )
    {
      MITK_ERROR << "Unable to extract slice." << std::endl;
      return false;
    }
      
    Contour* feedbackContour( FeedbackContourTool::GetFeedbackContour() );
    Contour::Pointer projectedContour = FeedbackContourTool::ProjectContourTo2DSlice( slice, feedbackContour, false, false ); // false: don't add 0.5 (done by FillContourInSlice)
                                                                                                                   // false: don't constrain the contour to the image's inside
    if (projectedContour.IsNull()) return false;

    FeedbackContourTool::FillContourInSlice( projectedContour, slice, m_PaintingPixelValue );

    // 5. Write the modified 2D working data slice back into the image
    OverwriteSliceImageFilter::Pointer slicewriter = OverwriteSliceImageFilter::New();
    slicewriter->SetInput( image );
    slicewriter->SetCreateUndoInformation( true );
    slicewriter->SetSliceImage( slice );
    slicewriter->SetSliceDimension( affectedDimension );
    slicewriter->SetSliceIndex( affectedSlice );
    slicewriter->SetTimeStep( positionEvent->GetSender()->GetTimeStep( image ) );
    slicewriter->Update();

    // 6. Make sure the result is drawn again --> is visible then. 
    assert( positionEvent->GetSender()->GetRenderWindow() );
    mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow());
  }
  else
  {
    MITK_ERROR << "FeedbackContourTool could not determine which slice of the image you are drawing on." << std::endl;
  }

  m_WholeImageContourInWorldCoordinates = NULL;
  m_SegmentationContourInWorldCoordinates = NULL;

  return true;
}

Member Data Documentation

Definition at line 67 of file mitkSetRegionTool.h.

Definition at line 65 of file mitkSetRegionTool.h.

Definition at line 70 of file mitkSetRegionTool.h.

Definition at line 68 of file mitkSetRegionTool.h.

Definition at line 71 of file mitkSetRegionTool.h.


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines