const mitk::NavigationDataReferenceTransformFilter::LandmarkPointContainer mitk::NavigationDataReferenceTransformFilter::GenerateReferenceLandmarks()
{
  LandmarkPointContainer lPoints;

  if(!m_ReferenceInputIndexes.empty())
  {
    TransformInitializerType::LandmarkPointType lPoint;

    if(m_ReferenceInputIndexes.size() < 3)
    {
      NavigationData::ConstPointer nD = this->GetInput(m_ReferenceInputIndexes.at(0));
      NavigationData::PositionType pos = nD->GetPosition();

      // fill position of reference source into sourcepoints container
      mitk::FillVector3D(lPoint, pos.GetElement(0), pos.GetElement(1), pos.GetElement(2));
      lPoints.push_back(lPoint);

      // generate additional virtual landmark point
      mitk::FillVector3D(lPoint, pos.GetElement(0), pos.GetElement(1)+100, pos.GetElement(2)); // reference source position + (0|100|0)
      lPoints.push_back(lPoint);

      // generate additional virtual landmark point
      mitk::FillVector3D(lPoint, pos.GetElement(0), pos.GetElement(1), pos.GetElement(2)+100); // reference source position + (0|0|100)
      lPoints.push_back(lPoint);
    }
   
    
    else if(m_ReferenceInputIndexes.size()>2)  // if there are at least 3 reference inputs
    {
      for(unsigned int i=0; i<m_ReferenceInputIndexes.size(); ++i)
      {
        NavigationData::ConstPointer nD = this->GetInput(m_ReferenceInputIndexes.at(i));
        NavigationData::PositionType pos = nD->GetPosition();
        mitk::FillVector3D(lPoint, pos.GetElement(0), pos.GetElement(1), pos.GetElement(2));
        lPoints.push_back(lPoint);
      }
    }

  }

  return lPoints;
}
コード例 #2
0
bool mitk::NavigationDataLandmarkTransformFilter::FindCorrespondentLandmarks(LandmarkPointContainer& sources, const LandmarkPointContainer& targets) const
{
  if (sources.size() < 6 || targets.size() < 6)
    return false;
  //throw std::invalid_argument("ICP correspondence finding needs at least 6 landmarks");

  /* lots of type definitions */
  typedef itk::PointSet<mitk::ScalarType, 3> PointSetType;
  //typedef itk::BoundingBox<PointSetType::PointIdentifier, PointSetType::PointDimension> BoundingBoxType;

  typedef itk::EuclideanDistancePointMetric< PointSetType, PointSetType> MetricType;
  //typedef MetricType::TransformType TransformBaseType;
  //typedef MetricType::TransformType::ParametersType ParametersType;
  //typedef TransformBaseType::JacobianType JacobianType;
  //typedef itk::Euler3DTransform< double > TransformType;
  typedef itk::VersorRigid3DTransform< double > TransformType;
  typedef TransformType ParametersType;
  typedef itk::PointSetToPointSetRegistrationMethod< PointSetType, PointSetType > RegistrationType;

  /* copy landmarks to itk pointsets for registration */
  PointSetType::Pointer sourcePointSet = PointSetType::New();
  unsigned int i = 0;
  for (LandmarkPointContainer::const_iterator it = sources.begin(); it != sources.end(); ++it)
  {
    PointSetType::PointType doublePoint;
    mitk::itk2vtk(*it, doublePoint); // copy mitk::ScalarType point into double point as workaround to ITK 3.10 bug
    sourcePointSet->SetPoint(i++, doublePoint /**it*/);
  }

  i = 0;
  PointSetType::Pointer targetPointSet = PointSetType::New();
  for (LandmarkPointContainer::const_iterator it = targets.begin(); it != targets.end(); ++it)
  {
    PointSetType::PointType doublePoint;
    mitk::itk2vtk(*it, doublePoint); // copy mitk::ScalarType point into double point as workaround to ITK 3.10 bug
    targetPointSet->SetPoint(i++, doublePoint /**it*/);
  }

  /* get centroid and extends of our pointsets */
  //BoundingBoxType::Pointer sourceBoundingBox = BoundingBoxType::New();
  //sourceBoundingBox->SetPoints(sourcePointSet->GetPoints());
  //sourceBoundingBox->ComputeBoundingBox();
  //BoundingBoxType::Pointer targetBoundingBox = BoundingBoxType::New();
  //targetBoundingBox->SetPoints(targetPointSet->GetPoints());
  //targetBoundingBox->ComputeBoundingBox();


  TransformType::Pointer transform = TransformType::New();
  transform->SetIdentity();
  //transform->SetTranslation(targetBoundingBox->GetCenter() - sourceBoundingBox->GetCenter());

  itk::LevenbergMarquardtOptimizer::Pointer optimizer = itk::LevenbergMarquardtOptimizer::New();
  optimizer->SetUseCostFunctionGradient(false);

  RegistrationType::Pointer registration = RegistrationType::New();

  // Scale the translation components of the Transform in the Optimizer
  itk::LevenbergMarquardtOptimizer::ScalesType scales(transform->GetNumberOfParameters());
  const double translationScale = 5000; //sqrtf(targetBoundingBox->GetDiagonalLength2())  * 1000; // dynamic range of translations
  const double rotationScale = 1.0; // dynamic range of rotations
  scales[0] = 1.0 / rotationScale;
  scales[1] = 1.0 / rotationScale;
  scales[2] = 1.0 / rotationScale;
  scales[3] = 1.0 / translationScale;
  scales[4] = 1.0 / translationScale;
  scales[5] = 1.0 / translationScale;
  //scales.Fill(0.01);
  unsigned long numberOfIterations = 80000;
  double gradientTolerance = 1e-10; // convergence criterion
  double valueTolerance = 1e-10; // convergence criterion
  double epsilonFunction = 1e-10; // convergence criterion
  optimizer->SetScales( scales );
  optimizer->SetNumberOfIterations( numberOfIterations );
  optimizer->SetValueTolerance( valueTolerance );
  optimizer->SetGradientTolerance( gradientTolerance );
  optimizer->SetEpsilonFunction( epsilonFunction );


  registration->SetInitialTransformParameters( transform->GetParameters() );
  //------------------------------------------------------
  // Connect all the components required for Registration
  //------------------------------------------------------
  MetricType::Pointer metric = MetricType::New();

  registration->SetMetric( metric );
  registration->SetOptimizer( optimizer );
  registration->SetTransform( transform );
  registration->SetFixedPointSet( targetPointSet );
  registration->SetMovingPointSet( sourcePointSet );

  try
  {
    //registration->StartRegistration();
    registration->Update();
  }
  catch( itk::ExceptionObject & e )
  {
    MITK_INFO << "Exception caught during ICP optimization: " << e;
    return false;
    //throw e;
  }
  MITK_INFO << "ICP successful: Solution = " << transform->GetParameters() << std::endl;
  MITK_INFO << "Metric value: " << metric->GetValue(transform->GetParameters());

  /* find point correspondences */
  //mitk::PointLocator::Pointer pointLocator = mitk::PointLocator::New();  // <<- use mitk::PointLocator instead of searching manually?
  //pointLocator->SetPoints()
  for (LandmarkPointContainer::const_iterator sourcesIt = sources.begin(); sourcesIt != sources.end(); ++sourcesIt)
  {
  }
  //MetricType::MeasureType closestDistances = metric->GetValue(transform->GetParameters());
  //unsigned int index = 0;
  LandmarkPointContainer sortedSources;
  for (LandmarkPointContainer::const_iterator targetsIt = targets.begin(); targetsIt != targets.end(); ++targetsIt)
  {
    double minDistance = itk::NumericTraits<double>::max();
    LandmarkPointContainer::iterator minDistanceIterator = sources.end();
    for (LandmarkPointContainer::iterator sourcesIt = sources.begin(); sourcesIt != sources.end(); ++sourcesIt)
    {
      TransformInitializerType::LandmarkPointType transformedSource = transform->TransformPoint(*sourcesIt);
      double dist = targetsIt->EuclideanDistanceTo(transformedSource);
      MITK_INFO << "target: " << *targetsIt << ", source: " << *sourcesIt << ", transformed source: " << transformedSource << ", dist: " << dist;
      if (dist < minDistance )
      {
        minDistanceIterator = sourcesIt;
        minDistance = dist;
      }
    }
    if (minDistanceIterator == sources.end())
      return false;
    MITK_INFO << "minimum distance point is: " << *minDistanceIterator << " (dist: " << targetsIt->EuclideanDistanceTo(transform->TransformPoint(*minDistanceIterator)) << ", minDist: " << minDistance << ")";
    sortedSources.push_back(*minDistanceIterator); // this point is assigned
    sources.erase(minDistanceIterator); // erase it from sources to avoid duplicate assigns
  }
  //for (LandmarkPointContainer::const_iterator sortedSourcesIt = sortedSources.begin(); targetsIt != sortedSources.end(); ++targetsIt)
  sources = sortedSources;
  return true;
}
void mitk::NavigationDataReferenceTransformFilter::GenerateData()
{
  LandmarkPointContainer newSourcePoints;  // for the quaternion transformed reference landmarks

  if(m_OneSourceRegistration) // check if less than 3 reference inputs
  {
    NavigationData::ConstPointer nd = this->GetInput(m_ReferenceInputIndexes.at(0));

    if (nd->IsDataValid() == false)
    {
      for (unsigned int i = 0; i < this->GetNumberOfOutputs() ; ++i)
      {
        mitk::NavigationData::Pointer output = this->GetOutput(i);
        assert(output);
        output->SetDataValid(false);
      }
      return;
    }

    QuaternionTransformType::Pointer referenceTransform = QuaternionTransformType::New();
    QuaternionTransformType::VnlQuaternionType doubleOrientation(nd->GetOrientation().x(), nd->GetOrientation().y(), nd->GetOrientation().z(), nd->GetOrientation().r()); // convert to double quaternion as workaround for ITK 3.10 bug
    
    referenceTransform->SetRotation(doubleOrientation);
    referenceTransform->SetOffset(nd->GetPosition().GetVectorFromOrigin());
    referenceTransform->Modified();

    for (NavigationDataReferenceTransformFilter::LandmarkPointContainer::const_iterator it = m_ReferencePoints.begin(); it != m_ReferencePoints.end(); ++it)
    {
      TransformInitializerType::LandmarkPointType rLPoint;  // reference landmark point
      rLPoint = referenceTransform->TransformPoint(*it);   
      newSourcePoints.push_back(rLPoint);   
    }
      
      this->UpdateLandmarkTransform(newSourcePoints, m_TargetPoints);
      m_SourcePoints = newSourcePoints;
  }
 

  if(this->IsInitialized() && !m_OneSourceRegistration && m_ReferenceRegistration)
    this->GenerateSourceLandmarks(); // generates landmarks from the moving points


  this->CreateOutputsForAllInputs();

  TransformInitializerType::LandmarkPointType lPointIn, lPointOut;

  for(unsigned int i = 0; i < this->GetNumberOfOutputs(); i++)
  {
    mitk::NavigationData::Pointer output = this->GetOutput(i);
    assert(output);
    mitk::NavigationData::ConstPointer input = this->GetInput(i);
    assert(input);

    if(input->IsDataValid() == false)
    {
      output->SetDataValid(false);
      continue;
    }
    output->Graft(input); // First, copy all information from input to output


    if(this->IsInitialized() == false)
      continue;

    mitk::NavigationData::PositionType tempCoordinate;
    tempCoordinate = input->GetPosition();

    lPointIn[0] = tempCoordinate[0];
    lPointIn[1] = tempCoordinate[1];
    lPointIn[2] = tempCoordinate[2];

    /* transform position */
    lPointOut = m_LandmarkTransform->TransformPoint(lPointIn);

    tempCoordinate[0] = lPointOut[0];
    tempCoordinate[1] = lPointOut[1];
    tempCoordinate[2] = lPointOut[2];

    output->SetPosition(tempCoordinate);  // update output navigation data with new position

    /* transform orientation */
    NavigationData::OrientationType quatIn = input->GetOrientation();
    vnl_quaternion<double> const vnlQuatIn(quatIn.x(), quatIn.y(), quatIn.z(), quatIn.r());
    m_QuaternionTransform->SetRotation(vnlQuatIn);


    m_QuaternionLandmarkTransform->SetMatrix(m_LandmarkTransform->GetRotationMatrix());
    m_QuaternionLandmarkTransform->Compose(m_QuaternionTransform, true);


    vnl_quaternion<double> vnlQuatOut = m_QuaternionLandmarkTransform->GetRotation();
    NavigationData::OrientationType quatOut( vnlQuatOut[0], vnlQuatOut[1], vnlQuatOut[2], vnlQuatOut[3]);

    output->SetOrientation(quatOut);
    output->SetDataValid(true);

  }
}