bool mitk::CorrectorAlgorithm::ImprovedHeimannCorrectionAlgorithm(itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer pic)
{
/*!
Some documentation (not by the original author)

TobiasHeimannCorrectionAlgorithm will be called, when the user has finished drawing a freehand line.

There should be different results, depending on the line's properties:

1. Without any prior segmentation, the start point and the end point of the drawn line will be
connected to a contour and the area enclosed by the contour will be marked as segmentation.

2. When the whole line is inside a segmentation, start and end point will be connected to
a contour and the area of this contour will be subtracted from the segmentation.

3. When the line starts inside a segmentation and ends outside with only a single
transition from segmentation to no-segmentation, nothing will happen.

4. When there are multiple transitions between inside-segmentation and
outside-segmentation, the line will be divided in so called segments. Each segment is
either fully inside or fully outside a segmentation. When it is inside a segmentation, its
enclosed area will be subtracted from the segmentation. When the segment is outside a
segmentation, its enclosed area it will be added to the segmentation.

The algorithm is described in full length in Tobias Heimann's diploma thesis
(MBI Technical Report 145, p. 37 - 40).
*/

  ContourModel::Pointer projectedContour = mitk::ContourModelUtils::ProjectContourTo2DSlice( m_WorkingImage, m_Contour, true, false );

  bool firstPointIsFillingColor = false;

  if (projectedContour.IsNull() ||
    projectedContour->GetNumberOfVertices() < 2 )
  {
    return false;
  }

  // Read the first point of the contour
  ContourModel::VertexIterator contourIter = projectedContour->Begin();
  if (contourIter == projectedContour->End())
    return false;
  itk::Index<2> previousIndex;
  previousIndex[0] = (*contourIter)->Coordinates[0];
  previousIndex[1] = (*contourIter)->Coordinates[1];
  ++contourIter;

  int currentColor = ( pic->GetPixel(previousIndex) == m_FillColor);
  firstPointIsFillingColor = currentColor;
  TSegData currentSegment;
  int countOfSegments = 1;


  bool firstSegment = true;
  ContourModel::VertexIterator contourEnd = projectedContour->End();
  for (; contourIter != contourEnd; ++contourIter)
  {
    // Get current point
    itk::Index<2> currentIndex;
    currentIndex[0] = (*contourIter)->Coordinates[0] +0.5;
    currentIndex[1] = (*contourIter)->Coordinates[1] +0.5;

    // Calculate length and slope
    double slopeX = currentIndex[0] - previousIndex[0];
    double slopeY = currentIndex[1] - previousIndex[1];
    double length = std::sqrt(slopeX * slopeX + slopeY * slopeY);
    double deltaX = slopeX / length;
    double deltaY = slopeY / length;

    for (double i = 0; i <= length && length > 0; i+=1)
    {
      itk::Index<2> temporaryIndex;
      temporaryIndex[0] = previousIndex[0] + deltaX * i;
      temporaryIndex[1] = previousIndex[1] + deltaY * i;
      if ( ! pic->GetLargestPossibleRegion().IsInside(temporaryIndex))
        continue;
      if ( (pic->GetPixel(temporaryIndex) == m_FillColor) != currentColor)
      {
        currentSegment.points.push_back(temporaryIndex);
        if ( ! firstSegment)
        {
          ModifySegment( currentSegment, pic);
        } else
        {
          firstSegment = false;
        }
        currentSegment = TSegData();
        ++countOfSegments;
        currentColor = (pic->GetPixel(temporaryIndex) == m_FillColor);
      }
      currentSegment.points.push_back(temporaryIndex);
    }
    previousIndex = currentIndex;
  }

  // Check if only on Segment
  if (firstSegment && currentSegment.points.size() > 0)
  {
      ContourModel::Pointer projectedContour = mitk::ContourModelUtils::ProjectContourTo2DSlice( m_WorkingImage, m_Contour, true, false );
      projectedContour->Close();
      if (firstPointIsFillingColor)
      {
        ContourModelUtils::FillContourInSlice(projectedContour, 0, m_WorkingImage, m_EraseColor);
      } else
      {
        ContourModelUtils::FillContourInSlice(projectedContour, 0, m_WorkingImage, m_FillColor);
      }
  }
  return true;
}
Esempio n. 2
0
/**
  Insert the point to the feedback contour,finish to build the contour and at the same time the painting function
  */
void mitk::PaintbrushTool::MouseMoved(mitk::InteractionEvent* interactionEvent, bool leftMouseButtonPressed)
{
  mitk::InteractionPositionEvent* positionEvent = dynamic_cast<mitk::InteractionPositionEvent*>( interactionEvent );

  CheckIfCurrentSliceHasChanged( positionEvent );

  if ( m_LastContourSize != m_Size )
  {
    UpdateContour( positionEvent );
    m_LastContourSize = m_Size;
  }

  Point3D worldCoordinates = positionEvent->GetPositionInWorld();
  Point3D indexCoordinates;

  m_WorkingSlice->GetGeometry()->WorldToIndex( worldCoordinates, indexCoordinates );

  MITK_DEBUG << "Mouse at W " << worldCoordinates << std::endl;
  MITK_DEBUG << "Mouse at I " << indexCoordinates << std::endl;

  // round to nearest voxel center (abort if this hasn't changed)
  if ( m_Size % 2 == 0 ) // even
  {
    indexCoordinates[0] = ROUND( indexCoordinates[0]);// /*+ 0.5*/) + 0.5;
    indexCoordinates[1] = ROUND( indexCoordinates[1]);// /*+ 0.5*/ ) + 0.5;
  }
  else // odd
  {
    indexCoordinates[0] = ROUND( indexCoordinates[0]  ) ;
    indexCoordinates[1] = ROUND( indexCoordinates[1] ) ;
  }

  static Point3D lastPos; // uninitialized: if somebody finds out how this can be initialized in a one-liner, tell me
  if ( fabs(indexCoordinates[0] - lastPos[0]) > mitk::eps ||
       fabs(indexCoordinates[1] - lastPos[1]) > mitk::eps ||
       fabs(indexCoordinates[2] - lastPos[2]) > mitk::eps ||
       leftMouseButtonPressed
     )
  {
    lastPos = indexCoordinates;
  }
  else
  {
    MITK_DEBUG << "." << std::flush;
    return;
  }

  MITK_DEBUG << "Mouse at C " << indexCoordinates;

  int timestep = positionEvent->GetSender()->GetTimeStep();

  ContourModel::Pointer contour = ContourModel::New();
  contour->Expand(timestep + 1);
  contour->SetClosed(true, timestep);

  ContourModel::VertexIterator it = m_MasterContour->Begin();
  ContourModel::VertexIterator end = m_MasterContour->End();

  while(it != end)
  {
    Point3D point = (*it)->Coordinates;
    point[0] += indexCoordinates[ 0 ];
    point[1] += indexCoordinates[ 1 ];

    contour->AddVertex( point, timestep );
    it++;
  }


  if (leftMouseButtonPressed)
  {
    FeedbackContourTool::FillContourInSlice( contour, timestep, m_WorkingSlice, m_PaintingPixelValue );
    m_WorkingNode->SetData(m_WorkingSlice);
    m_WorkingNode->Modified();
  }

  // visualize contour
  ContourModel::Pointer displayContour = this->GetFeedbackContour();
  displayContour->Clear();

  ContourModel::Pointer tmp = FeedbackContourTool::BackProjectContourFrom2DSlice( m_WorkingSlice->GetGeometry(), /*displayContour*/contour );

  // copy transformed contour into display contour
  it =  tmp->Begin();
  end = tmp->End();

  while(it != end)
  {
    Point3D point = (*it)->Coordinates;

    displayContour->AddVertex( point, timestep );
    it++;
  }

  m_FeedbackContourNode->GetData()->Modified();

  assert( positionEvent->GetSender()->GetRenderWindow() );

  RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() );
}