VTK/Examples/Cxx/Filtering/IterativeClosestPointsTransform
From KitwarePublic
< VTK | Examples | Cxx
Revision as of 12:10, 6 October 2010 by Daviddoria (talk | contribs) (moved VTK/Examples/Cxx/Filters/IterativeClosestPointsTransform to VTK/Examples/Cxx/Filtering/IterativeClosestPointsTransform)
IterativeClosestPointsTransform.cxx
/*
This demo produces target points which are at the origin and unit length along each axis.
It then perturbs the points and shifts each of them .3 in +y direction -
the resulting points are the "source" points. It then attempts to move the source points as
close as possible to the target points. The noise is added to make the example more realistic.
Also, the noise ensures nothing was done wrong (i.e. accidentally using the target points as
the result and claiming it worked perfectly when in fact nothing happened!)
*/
#include <vtkSmartPointer.h>
#include <vtkTransform.h>
#include <vtkVertexGlyphFilter.h>
#include <vtkPoints.h>
#include <vtkPolyData.h>
#include <vtkCellArray.h>
#include <vtkIterativeClosestPointTransform.h>
#include <vtkTransformPolyDataFilter.h>
#include <vtkLandmarkTransform.h>
#include <vtkMath.h>
#include <vtkMatrix4x4.h>
#include <vtkXMLPolyDataWriter.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkXMLPolyDataReader.h>
#include <vtkProperty.h>
namespace
{
void CreatePolyData(vtkSmartPointer<vtkPolyData> polydata);
void PerturbPolyData(vtkSmartPointer<vtkPolyData> polydata);
void TranslatePolyData(vtkSmartPointer<vtkPolyData> polydata);
}
int main(int argc, char *argv[])
{
vtkSmartPointer<vtkPolyData> source =
vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkPolyData> target =
vtkSmartPointer<vtkPolyData>::New();
if(argc == 3)
{
std::cout << "Reading data..." << std::endl;
std::string strSource = argv[1];
std::string strTarget = argv[2];
vtkSmartPointer<vtkXMLPolyDataReader> sourceReader =
vtkSmartPointer<vtkXMLPolyDataReader>::New();
sourceReader->SetFileName(strSource.c_str());
sourceReader->Update();
source->ShallowCopy(sourceReader->GetOutput());
vtkSmartPointer<vtkXMLPolyDataReader> targetReader =
vtkSmartPointer<vtkXMLPolyDataReader>::New();
targetReader->SetFileName(strTarget.c_str());
targetReader->Update();
target->ShallowCopy(targetReader->GetOutput());
}
else
{
std::cout << "Creating data..." << std::endl;
CreatePolyData(source);
target->ShallowCopy(source);
TranslatePolyData(target);
PerturbPolyData(target);
}
// Setup ICP transform
vtkSmartPointer<vtkIterativeClosestPointTransform> icp =
vtkSmartPointer<vtkIterativeClosestPointTransform>::New();
icp->SetSource(source);
icp->SetTarget(target);
icp->GetLandmarkTransform()->SetModeToRigidBody();
icp->SetMaximumNumberOfIterations(20);
//icp->StartByMatchingCentroidsOn();
icp->Modified();
icp->Update();
// Get the resulting transformation matrix (this matrix takes the source points to the target points)
vtkSmartPointer<vtkMatrix4x4> m = icp->GetMatrix();
std::cout << "The resulting matrix is: " << *m << std::endl;
// Transform the source points by the ICP solution
vtkSmartPointer<vtkTransformPolyDataFilter> icpTransformFilter =
vtkSmartPointer<vtkTransformPolyDataFilter>::New();
icpTransformFilter->SetInput(source);
icpTransformFilter->SetTransform(icp);
icpTransformFilter->Update();
/*
// If you need to take the target points to the source points, the matrix is:
icp->Inverse();
vtkSmartPointer<vtkMatrix4x4> minv = icp->GetMatrix();
std::cout << "The resulting inverse matrix is: " << *minv << std::cout;
*/
// Visualize
vtkSmartPointer<vtkPolyDataMapper> sourceMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
sourceMapper->SetInputConnection(source->GetProducerPort());
vtkSmartPointer<vtkActor> sourceActor =
vtkSmartPointer<vtkActor>::New();
sourceActor->SetMapper(sourceMapper);
sourceActor->GetProperty()->SetColor(1,0,0);
sourceActor->GetProperty()->SetPointSize(4);
vtkSmartPointer<vtkPolyDataMapper> targetMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
targetMapper->SetInputConnection(target->GetProducerPort());
vtkSmartPointer<vtkActor> targetActor =
vtkSmartPointer<vtkActor>::New();
targetActor->SetMapper(targetMapper);
targetActor->GetProperty()->SetColor(0,1,0);
targetActor->GetProperty()->SetPointSize(4);
vtkSmartPointer<vtkPolyDataMapper> solutionMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
solutionMapper->SetInputConnection(icpTransformFilter->GetOutputPort());
vtkSmartPointer<vtkActor> solutionActor =
vtkSmartPointer<vtkActor>::New();
solutionActor->SetMapper(solutionMapper);
solutionActor->GetProperty()->SetColor(0,0,1);
solutionActor->GetProperty()->SetPointSize(3);
// Create a renderer, render window, and interactor
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
// Add the actor to the scene
renderer->AddActor(sourceActor);
renderer->AddActor(targetActor);
renderer->AddActor(solutionActor);
renderer->SetBackground(.3, .6, .3); // Background color green
// Render and interact
renderWindow->Render();
renderWindowInteractor->Start();
return EXIT_SUCCESS;
}
namespace // anonymous
{
void CreatePolyData(vtkSmartPointer<vtkPolyData> polydata)
{
// This function creates a set of 4 points (the origin and a point unit distance along each axis)
vtkSmartPointer<vtkPoints> points =
vtkSmartPointer<vtkPoints>::New();
// Create points
double origin[3] = {0.0, 0.0, 0.0};
points->InsertNextPoint(origin);
double p1[3] = {1.0, 0.0, 0.0};
points->InsertNextPoint(p1);
double p2[3] = {0.0, 1.0, 0.0};
points->InsertNextPoint(p2);
double p3[3] = {0.0, 0.0, 1.0};
points->InsertNextPoint(p3);
vtkSmartPointer<vtkPolyData> temp =
vtkSmartPointer<vtkPolyData>::New();
temp->SetPoints(points);
vtkSmartPointer<vtkVertexGlyphFilter> vertexFilter =
vtkSmartPointer<vtkVertexGlyphFilter>::New();
vertexFilter->SetInputConnection(temp->GetProducerPort());
vertexFilter->Update();
polydata->ShallowCopy(vertexFilter->GetOutput());
}
void PerturbPolyData(vtkSmartPointer<vtkPolyData> polydata)
{
vtkSmartPointer<vtkPoints> points =
vtkSmartPointer<vtkPoints>::New();
points->ShallowCopy(polydata->GetPoints());
vtkMath::RandomSeed(time(NULL));
for(unsigned int i = 0; i < points->GetNumberOfPoints(); i++)
{
double p[3];
points->GetPoint(i, p);
for(unsigned int j = 0; j < 3; j++)
{
double pointNoise = vtkMath::Random(-0.1, 0.1);
p[j] = p[j] + pointNoise;
}
points->SetPoint(i, p);
}
polydata->SetPoints(points);
}
void TranslatePolyData(vtkSmartPointer<vtkPolyData> polydata)
{
vtkSmartPointer<vtkTransform> transform =
vtkSmartPointer<vtkTransform>::New();
transform->Translate(0,.3,0);
vtkSmartPointer<vtkTransformPolyDataFilter> transformFilter =
vtkSmartPointer<vtkTransformPolyDataFilter>::New();
transformFilter->SetInputConnection(polydata->GetProducerPort());
transformFilter->SetTransform(transform);
transformFilter->Update();
polydata->ShallowCopy(transformFilter->GetOutput());
}
} // end anonymous namespace
CMakeLists.txt
PROJECT(ICP)
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
FIND_PACKAGE(VTK REQUIRED)
INCLUDE(${VTK_USE_FILE})
ADD_EXECUTABLE(ICP ICP.cxx)
TARGET_LINK_LIBRARIES(ICP vtkHybrid)