2017년 1월 3일 화요일

[Vtk] Registration - Landmark Transform


Landmark를 가지고 있는 경우 source -> target으로 정합한 매트릭스를 반환한다.

void myLandmarkTransform(vtkSmartPointer<vtkPolyData> source, vtkSmartPointer<vtkPolyData> target)
{
      vtkSmartPointer<vtkLandmarkTransform> landmarkTransform = vtkSmartPointer<vtkLandmarkTransform>::New();
      landmarkTransform->SetSourceLandmarks(source->GetPoints());
      landmarkTransform->SetTargetLandmarks(target->GetPoints());
      landmarkTransform->SetModeToRigidBody(); // 형태를 유지한다;
      landmarkTransform->Update();

      vtkSmartPointer<vtkTransformPolyDataFilter> transformFilter = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
      transformFilter->SetInputData(source);
      transformFilter->SetTransform(landmarkTransform);
      transformFilter->Update();

      vtkMatrix4x4* mat = landmarkTransform->GetMatrix();
      std::cout << "Matrix: " << *mat << std::endl;

      source->ShallowCopy(transformFilter->GetOutput());
}

vtkLandmarkTransform 의 사용법은 간단하다.
이동을 시킬 vtkPoints 를 SetSourceLandmarks 에 넣고
정합 대산인 vtkPoints 를 SetTargetLandmarks 에 넣는다.
모드를 설정한 뒤 Update() 를 호출한다. 정합 모드는 VTK_LANDMARK_SIMILARITY 가 기본 값이다.

vtkLandmarkTransform은 3가지의 모드가 있다.
landmarkTransform->SetModeToRigidBody() : rotation and traslation only
landmarkTransform->SetModeToSimilarity() : rotation and traslation and isotropic scaling (default)
landmarkTransform->SetModeToAffine()


- 정합 전 (source : white, target : red)
 

- 정합 후
 


정합 후 결과 확인을 위한 Sample Code (두 Polydata의 점이 완전히 쌍을 이루는 경우)
double calculateDistanceBetweenPoints(vtkSmartPointer<vtkPoints> p0, vtkSmartPointer<vtkPoints> p1)
{
      double totalDistance = 0;
      double averageDistance = 0;

      if (p0->GetNumberOfPoints() == p1->GetNumberOfPoints() && p0->GetNumberOfPoints() != 0)
      {
            int numPoints = p0->GetNumberOfPoints();
            double squaredDistance;
            for (int i = 0; i < numPoints; i++)
            {
                  squaredDistance = vtkMath::Distance2BetweenPoints(p0->GetPoint(i), p1->GetPoint(i));
                  totalDistance += sqrt(squaredDistance);
            }

            averageDistance = totalDistance / numPoints;
      }

      return averageDistance;
}





댓글 없음:

댓글 쓰기