Discussion:
[vtkusers] Several point clouds alignment using ICP
nuno.jf
2011-02-22 11:53:03 UTC
Permalink
Hi there,

Currently, I need to align and display a set of 58 point clouds (in .wrl
file format) using ICP.
The code I have right now, is the "common" one, which receives two point
clouds and aligns them.
What I have to do (but don't know how ={ ) is a cycle for ICP to read each
point cloud and align all of them.
In the end, a volume file of the aligned point clouds must be created.
Can anyone please help me?

Please find attached three wrl files I need to align in a zipped folder
http://vtk.1045678.n5.nabble.com/file/n3395391/hand_teste1_15_12_2010_01_001.wrl
hand_teste1_15_12_2010_01_001.wrl
http://vtk.1045678.n5.nabble.com/file/n3395391/wrl_files.zip wrl_files.zip
(of the total 58 files).


Thank you very much!

Nuno


----------------ICP CODE I currently have -------------------
// icp

// Iterative Closest Point (VTK)

#include "vtkVRMLImporter.h"
#include "vtkIterativeClosestPointTransform.h"

#include "vtkTransform.h"
#include "vtkTransformPolyDataFilter.h"
#include "vtkLandmarkTransform.h"

#include "vtkPolyDataReader.h"
#include "vtkPolyDataWriter.h"
#include "vtkPolyData.h"
#include "vtkPolyDataMapper.h"
#include "vtkPolyDataNormals.h"
#include "vtkSmoothPolyDataFilter.h"
#include "vtkDecimatePro.h"

#include "vtkGaussianSplatter.h"
#include "vtkContourFilter.h"

#include "vtkAxes.h"
#include "vtkTubeFilter.h"
#include "vtkCamera.h"
#include "vtkActor.h"
#include "vtkProperty.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"

// main function

int main( int argc, char *argv[] )
{

// Point Cloud 1
//---------------------------------------------------------
vtkVRMLImporter *imp1 = vtkVRMLImporter::New();
imp1 -> SetFileName(
"C:/Users/Nuno/Documents/Faculdade/LIGHTSCAN/bin/ICP/Debug/hand_teste1_15_12_2010_01_001.wrl"
);
imp1 -> Read();
imp1 -> Update();

vtkDataSet *pDataset1;
vtkActorCollection *actors1 = imp1 -> GetRenderer()->GetActors();
actors1 -> InitTraversal();
pDataset1 = actors1 -> GetNextActor()->GetMapper()->GetInput();

vtkPolyData *polyData1 = vtkPolyData::SafeDownCast( pDataset1 );
polyData1 -> Update();

// Point Cloud 2
//---------------------------------------------------------
vtkVRMLImporter *imp2 = vtkVRMLImporter::New();
imp2 -> SetFileName(
"C:/Users/Nuno/Documents/Faculdade/LIGHTSCAN/bin/ICP/Debug/hand_teste1_15_12_2010_01_003.wrl"
);
imp2 -> Read();
imp2 -> Update();

vtkDataSet *pDataset2;
vtkActorCollection *actors2 = imp2 -> GetRenderer()->GetActors();
actors2 -> InitTraversal();
pDataset2 = actors2 -> GetNextActor()->GetMapper()->GetInput();

vtkPolyData *polyData2 = vtkPolyData::SafeDownCast( pDataset2 );
polyData2 -> Update();

std::cout << "Number of points in cloud 1 = " << polyData1 ->
GetNumberOfPoints() << std::endl;
std::cout << "Number of points in cloud 2 = " << polyData2 ->
GetNumberOfPoints() << std::endl;

// ==============================================================
//
// ICP - VTK
//
// ==============================================================

vtkIterativeClosestPointTransform * icp =
vtkIterativeClosestPointTransform::New();

// Set SOURCE and TARGET points
//---------------------------------------------------------
//icp -> SetTarget( reader_PolyData1 -> GetOutput() );
//icp -> SetSource( reader_PolyData2 -> GetOutput() );
icp -> SetTarget( polyData1 );
icp -> SetSource( polyData2 ); //

// Configure ICP transform
//---------------------------------------------------------
//icp -> SetStartByMatchingCentroids(1);
icp -> StartByMatchingCentroidsOff();
icp -> GetLandmarkTransform()->SetModeToRigidBody();
//icp -> GetLandmarkTransform()->SetModeToAffine();
//icp -> SetCheckMeanDistance(1);
//icp -> SetMeanDistanceModeToAbsoluteValue();
icp -> SetMeanDistanceModeToRMS();
icp -> SetMaximumNumberOfLandmarks(2000);
icp -> SetMaximumNumberOfIterations(250);
icp -> SetMaximumMeanDistance(0.00001);
icp -> Update();

std::cout << "ICP Mean Distance RMS = " << icp -> GetMeanDistance() <<
std::endl;

// transform SOURCE to obtain TARGET
//---------------------------------------------------------
vtkTransformPolyDataFilter * transform = vtkTransformPolyDataFilter::New();

transform -> SetTransform( icp );
transform -> SetInput( polyData2 );
transform -> Update();

//transform -> PrintSelf( std::cout, 0);
std::cout << "ICP transform done." << std::endl;


// ==============================================================
//
// VTK RENDERING
//
// ==============================================================
vtkRenderer *ren = vtkRenderer::New();
vtkRenderWindow *renWin = vtkRenderWindow::New();
vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
renWin -> AddRenderer(ren);
iren -> SetRenderWindow(renWin);
ren -> SetBackground(1, 1, 1);
renWin -> SetSize(800, 600);

// axes
//---------------------------------------------------------
double axis_scale_factor = 100.0; // mm
int num_sides = 6;
vtkAxes *axes = vtkAxes::New();
vtkTubeFilter *axesTubes = vtkTubeFilter::New();
vtkPolyDataMapper *axesMapper = vtkPolyDataMapper::New();
vtkActor *axesActor = vtkActor::New();
axes -> SetOrigin( 0.0, 0.0, 0.0 );
axes -> SetScaleFactor( axis_scale_factor );
axesTubes -> SetInput( axes -> GetOutput());
axesTubes -> SetRadius( axes -> GetScaleFactor()/axis_scale_factor );
axesTubes -> SetNumberOfSides( num_sides );
axesMapper -> SetInput( axesTubes -> GetOutput() );
axesActor -> SetMapper( axesMapper );

//ren -> AddActor( axesActor );
axesMapper -> Delete();
axesTubes -> Delete();
axes -> Delete();


// TARGET - PolyData1 - Points Red
//---------------------------------------------------------
vtkPolyDataMapper * rawpointsMapper1 = vtkPolyDataMapper::New();
vtkActor * rawpointsActor1 = vtkActor::New();
//rawpointsMapper1 -> SetInput( reader_PolyData1 -> GetOutput() );
rawpointsMapper1 -> SetInput( polyData1 );
rawpointsMapper1 -> ScalarVisibilityOff();
rawpointsActor1 -> SetMapper( rawpointsMapper1 );
rawpointsActor1 -> GetProperty() -> SetColor(1, 0, 0);

ren -> AddActor( rawpointsActor1 );
rawpointsMapper1 -> Delete();


// SOURCE - PolyData2 - Points Green
//---------------------------------------------------------
vtkPolyDataMapper * rawpointsMapper2 = vtkPolyDataMapper::New();
vtkActor * rawpointsActor2 = vtkActor::New();

rawpointsMapper2 -> SetInput( polyData2 );
rawpointsMapper2 -> ScalarVisibilityOff();
rawpointsActor2 -> SetMapper( rawpointsMapper2 );
rawpointsActor2 -> GetProperty() -> SetColor(0, 1, 0);

ren -> AddActor( rawpointsActor2 );
rawpointsMapper2 -> Delete();


// ICP - PolyData2 TRANSFORMED - Points Blue
//---------------------------------------------------------
vtkPolyDataMapper * rawpointsMapper3 = vtkPolyDataMapper::New();
vtkActor * rawpointsActor3 = vtkActor::New();

rawpointsMapper3 -> SetInput( transform -> GetOutput() );
//rawpointsMapper3 -> SetInput( TF -> GetOutput() );
rawpointsMapper3 -> ScalarVisibilityOff();
rawpointsActor3 -> SetMapper( rawpointsMapper3 );
rawpointsActor3 -> GetProperty() -> SetColor(0, 0, 1);

ren -> AddActor( rawpointsActor3 );
rawpointsMapper3 -> Delete();

// Surface Rendering

renWin -> Render();
iren -> Start();

// Delete VTK objects

ren -> RemoveActor( axesActor );
ren -> RemoveActor( rawpointsActor1 );
ren -> RemoveActor( rawpointsActor2 );
ren -> RemoveActor( rawpointsActor3 );

rawpointsActor1 -> Delete();
rawpointsActor2 -> Delete();
rawpointsActor3 -> Delete();

ren -> Delete();
iren -> Delete();
renWin -> Delete();

/* ============================================================ */
return 0;

}
--
View this message in context: http://vtk.1045678.n5.nabble.com/Several-point-clouds-alignment-using-ICP-tp3395391p3395391.html
Sent from the VTK - Users mailing list archive at Nabble.com.
David Doria
2011-02-22 12:44:26 UTC
Permalink
Post by nuno.jf
Hi there,
Currently, I need to align and display a set of 58 point clouds (in .wrl
file format) using ICP.
The code I have right now, is the "common" one, which receives two point
clouds and aligns them.
What I have to do (but don't know how ={ ) is a cycle for ICP to read each
point cloud and align all of them.
In the end, a volume file of the aligned point clouds must be created.
Can anyone please help me?
Please find attached three wrl files I need to align in a zipped folder
http://vtk.1045678.n5.nabble.com/file/n3395391/hand_teste1_15_12_2010_01_001.wrl
hand_teste1_15_12_2010_01_001.wrl
http://vtk.1045678.n5.nabble.com/file/n3395391/wrl_files.zip wrl_files.zip
(of the total 58 files).
Thank you very much!
Nuno
----------------ICP CODE I currently have -------------------
// icp
// Iterative Closest Point (VTK)
#include "vtkVRMLImporter.h"
#include "vtkIterativeClosestPointTransform.h"
#include "vtkTransform.h"
#include "vtkTransformPolyDataFilter.h"
#include "vtkLandmarkTransform.h"
#include "vtkPolyDataReader.h"
#include "vtkPolyDataWriter.h"
#include "vtkPolyData.h"
#include "vtkPolyDataMapper.h"
#include "vtkPolyDataNormals.h"
#include "vtkSmoothPolyDataFilter.h"
#include "vtkDecimatePro.h"
#include "vtkGaussianSplatter.h"
#include "vtkContourFilter.h"
#include "vtkAxes.h"
#include "vtkTubeFilter.h"
#include "vtkCamera.h"
#include "vtkActor.h"
#include "vtkProperty.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
// main function
int main( int argc, char *argv[] )
{
       // Point Cloud 1
       //---------------------------------------------------------
       vtkVRMLImporter *imp1 = vtkVRMLImporter::New();
       imp1 -> SetFileName(
"C:/Users/Nuno/Documents/Faculdade/LIGHTSCAN/bin/ICP/Debug/hand_teste1_15_12_2010_01_001.wrl"
);
       imp1 -> Read();
       imp1 -> Update();
       vtkDataSet *pDataset1;
       vtkActorCollection *actors1 = imp1 -> GetRenderer()->GetActors();
       actors1 -> InitTraversal();
       pDataset1 = actors1 -> GetNextActor()->GetMapper()->GetInput();
       vtkPolyData *polyData1 = vtkPolyData::SafeDownCast( pDataset1 );
       polyData1 -> Update();
       // Point Cloud 2
       //---------------------------------------------------------
       vtkVRMLImporter *imp2 = vtkVRMLImporter::New();
       imp2 -> SetFileName(
"C:/Users/Nuno/Documents/Faculdade/LIGHTSCAN/bin/ICP/Debug/hand_teste1_15_12_2010_01_003.wrl"
);
       imp2 -> Read();
       imp2 -> Update();
       vtkDataSet *pDataset2;
       vtkActorCollection *actors2 = imp2 -> GetRenderer()->GetActors();
       actors2 -> InitTraversal();
       pDataset2 = actors2 -> GetNextActor()->GetMapper()->GetInput();
       vtkPolyData *polyData2 = vtkPolyData::SafeDownCast( pDataset2 );
       polyData2 -> Update();
       std::cout << "Number of points in cloud 1 = " << polyData1 ->
GetNumberOfPoints() << std::endl;
       std::cout << "Number of points in cloud 2 = " << polyData2 ->
GetNumberOfPoints() << std::endl;
       // ==============================================================
       //
       // ICP - VTK
       //
       // ==============================================================
       vtkIterativeClosestPointTransform * icp =
vtkIterativeClosestPointTransform::New();
       // Set SOURCE and TARGET points
       //---------------------------------------------------------
       //icp -> SetTarget( reader_PolyData1 -> GetOutput() );
       //icp -> SetSource( reader_PolyData2 -> GetOutput() );
       icp -> SetTarget( polyData1 );
       icp -> SetSource( polyData2 ); //
       // Configure ICP transform
       //---------------------------------------------------------
       //icp -> SetStartByMatchingCentroids(1);
       icp -> StartByMatchingCentroidsOff();
       icp -> GetLandmarkTransform()->SetModeToRigidBody();
       //icp -> GetLandmarkTransform()->SetModeToAffine();
       //icp -> SetCheckMeanDistance(1);
       //icp -> SetMeanDistanceModeToAbsoluteValue();
       icp -> SetMeanDistanceModeToRMS();
       icp -> SetMaximumNumberOfLandmarks(2000);
       icp -> SetMaximumNumberOfIterations(250);
       icp -> SetMaximumMeanDistance(0.00001);
       icp -> Update();
       std::cout << "ICP Mean Distance RMS = " << icp -> GetMeanDistance() <<
std::endl;
       // transform SOURCE to obtain TARGET
       //---------------------------------------------------------
       vtkTransformPolyDataFilter * transform = vtkTransformPolyDataFilter::New();
       transform -> SetTransform( icp );
       transform -> SetInput( polyData2 );
       transform -> Update();
       //transform -> PrintSelf( std::cout, 0);
       std::cout << "ICP transform done." << std::endl;
       // ==============================================================
       //
       // VTK  RENDERING
       //
       // ==============================================================
       vtkRenderer                    *ren = vtkRenderer::New();
       vtkRenderWindow             *renWin = vtkRenderWindow::New();
       vtkRenderWindowInteractor     *iren = vtkRenderWindowInteractor::New();
       renWin  -> AddRenderer(ren);
       iren    -> SetRenderWindow(renWin);
       ren     -> SetBackground(1, 1, 1);
       renWin  -> SetSize(800, 600);
       // axes
       //---------------------------------------------------------
       double axis_scale_factor = 100.0;       // mm
       int num_sides = 6;
       vtkAxes                                 *axes = vtkAxes::New();
       vtkTubeFilter      *axesTubes = vtkTubeFilter::New();
       vtkPolyDataMapper *axesMapper = vtkPolyDataMapper::New();
       vtkActor                   *axesActor = vtkActor::New();
       axes            -> SetOrigin( 0.0, 0.0, 0.0 );
       axes            -> SetScaleFactor( axis_scale_factor );
       axesTubes       -> SetInput( axes -> GetOutput());
       axesTubes       -> SetRadius( axes -> GetScaleFactor()/axis_scale_factor );
       axesTubes       -> SetNumberOfSides( num_sides );
       axesMapper      -> SetInput( axesTubes -> GetOutput() );
       axesActor       -> SetMapper( axesMapper );
       //ren -> AddActor( axesActor );
       axesMapper -> Delete();
       axesTubes -> Delete();
       axes -> Delete();
       // TARGET - PolyData1 - Points Red
       //---------------------------------------------------------
       vtkPolyDataMapper * rawpointsMapper1 = vtkPolyDataMapper::New();
       vtkActor                   * rawpointsActor1 = vtkActor::New();
       //rawpointsMapper1 -> SetInput( reader_PolyData1 -> GetOutput() );
       rawpointsMapper1 -> SetInput( polyData1 );
       rawpointsMapper1 -> ScalarVisibilityOff();
       rawpointsActor1  -> SetMapper( rawpointsMapper1 );
       rawpointsActor1  -> GetProperty() -> SetColor(1, 0, 0);
       ren -> AddActor( rawpointsActor1 );
       rawpointsMapper1 -> Delete();
       // SOURCE - PolyData2 - Points Green
       //---------------------------------------------------------
       vtkPolyDataMapper * rawpointsMapper2 = vtkPolyDataMapper::New();
       vtkActor                   * rawpointsActor2 = vtkActor::New();
       rawpointsMapper2 -> SetInput( polyData2 );
       rawpointsMapper2 -> ScalarVisibilityOff();
       rawpointsActor2  -> SetMapper( rawpointsMapper2 );
       rawpointsActor2  -> GetProperty() -> SetColor(0, 1, 0);
       ren -> AddActor( rawpointsActor2 );
       rawpointsMapper2 -> Delete();
       // ICP - PolyData2 TRANSFORMED - Points Blue
       //---------------------------------------------------------
       vtkPolyDataMapper * rawpointsMapper3 = vtkPolyDataMapper::New();
       vtkActor                   * rawpointsActor3 = vtkActor::New();
       rawpointsMapper3 -> SetInput( transform -> GetOutput() );
       //rawpointsMapper3 -> SetInput( TF -> GetOutput() );
       rawpointsMapper3 -> ScalarVisibilityOff();
       rawpointsActor3  -> SetMapper( rawpointsMapper3 );
       rawpointsActor3  -> GetProperty() -> SetColor(0, 0, 1);
       ren -> AddActor( rawpointsActor3 );
       rawpointsMapper3  -> Delete();
       // Surface Rendering
       renWin -> Render();
       iren -> Start();
       // Delete VTK objects
       ren -> RemoveActor( axesActor );
       ren -> RemoveActor( rawpointsActor1 );
       ren -> RemoveActor( rawpointsActor2 );
       ren -> RemoveActor( rawpointsActor3 );
       rawpointsActor1 -> Delete();
       rawpointsActor2 -> Delete();
       rawpointsActor3 -> Delete();
       ren -> Delete();
       iren -> Delete();
       renWin -> Delete();
       /* ============================================================ */
       return 0;
}
--
View this message in context: http://vtk.1045678.n5.nabble.com/Several-point-clouds-alignment-using-ICP-tp3395391p3395391.html
I believe that is what the ProcrustesAlignmentFilter is for:

http://www.vtk.org/Wiki/VTK/Examples/Cxx/PolyData/ProcrustesAlignmentFilter

David
nuno.jf
2011-02-22 13:31:24 UTC
Permalink
Thank you for your message David.

1) Will I be able to open wrl files with ProcrustesAlignmentFilter?

2) This algorithm is only working for 3 objects. ICP is working for 2
objects. The question is that I don't know how can I implement a cycle for
the alignment of 58 point clouds. Should I find a way to store the
transformation applied to each pair of objects each time I run the cycle
and, in the end, apply all transformations to all objects?

Thank you very much,

Nuno
--
View this message in context: http://vtk.1045678.n5.nabble.com/Several-point-clouds-alignment-using-ICP-tp3395391p3395491.html
Sent from the VTK - Users mailing list archive at Nabble.com.
David Doria
2011-02-22 13:36:14 UTC
Permalink
Post by nuno.jf
Thank you for your message David.
1) Will I be able to open wrl files with ProcrustesAlignmentFilter?
2) This algorithm is only working for 3 objects. ICP is working for 2
objects. The question is that I don't know how can I implement a cycle for
the alignment of 58 point clouds. Should I find a way to store the
transformation applied to each pair of objects each time I run the cycle
and, in the end, apply all transformations to all objects?
Thank you very much,
Nuno
The filter is independent of the data files that you read - you have
to first read them, then pass them to the filter.

The example can be easily extended to more than 3 inputs by simply
changing SetNumberOfInputs(n).

David
nuno.jf
2011-03-04 12:28:34 UTC
Permalink
Hi there,

I used ProcrustesAlignmentFilter but the problem is that the input point
clouds need to have the exact same number of points. So it doesn't work
well..If I use vtkMaskPoints and set the maximum number of points to the
same value, I believe it might work...

At this moment I am using the following pipelin:

Read polydata1; Read polydata 2 -> vtkTransformPolyDataFilter to apply a
know transformation to polydata2 -> vtkIterativeClosestPointTransform to try
to find transformation to align polydata 2 with polydata1 ->
vtkTransformPolyDataFilter to apply the transformation given by ICP -
vtkAppendPolyData to append both point clouds.
The problem is that using ICP I can't get a correct transformation for the
alignment, even with a high number of iterations set up...

I am thinking on getting back to ProcrustesAlignmentFilter. I am using
VTKCleanPolydata to downsample the point clouds but I don't know what
SetTolerance exactly does. I mean, I know that it changes the way the point
cloud is sub sampled, but I don't know exactly what kind of relationship it
sets between the input and the output.

So, can anyone give me some advises regarding this subject? Basically, I
just need to align 58 point clouds that have, at this moment, different
number of points.
Any help is greatly appreciated!
Best regards,

Nuno

--
View this message in context: http://vtk.1045678.n5.nabble.com/Several-point-clouds-alignment-using-ICP-tp3395391p3409401.html
Sent from the VTK - Users mailing list archive at Nabble.com.
Tim Hutton
2011-03-04 14:31:35 UTC
Permalink
Ah, yes, if your points don't correspond across the datasets then
Procrustes won't do what you want. For example, if point 832 is the
tip of a dog's nose in dataset one but the end of the dog's tail in
dataset two then Procrustes will align your dogs up back-to-front.

Sounds like you need to get ICP working first, then use it to align
the surfaces together. Procrustes works by finding the average shape,
aligning the average to dataset one, then aligning the other datasets
to the average. When the surfaces stop moving you're done. So you
could do something similar with ICP: align all the surfaces to dataset
one. There's no way to compute an average shape though, so that's all
you could do.

To get ICP working you might need to give it some hints. Do you know
anything about the correspondence? Do the surfaces have sufficient
overlapping parts for ICP to work? Do the surfaces have a sufficiently
similar shape for ICP to work?
Post by nuno.jf
Hi there,
I used ProcrustesAlignmentFilter but the problem is that the input point
clouds need to have the exact same number of points. So it doesn't work
well..If I use vtkMaskPoints  and set the maximum number of points to the
same value, I believe it might work...
Read polydata1; Read polydata 2 -> vtkTransformPolyDataFilter to apply a
know transformation to polydata2 -> vtkIterativeClosestPointTransform to try
to find transformation to align polydata 2 with polydata1 ->
vtkTransformPolyDataFilter to apply the transformation given by ICP -
vtkAppendPolyData to append both point clouds.
The problem is that using ICP I can't get a correct transformation for the
alignment, even with a high number of iterations set up...
I am thinking on getting back to ProcrustesAlignmentFilter. I am using
VTKCleanPolydata to downsample the point clouds but I don't know what
SetTolerance exactly does. I mean, I know that it changes the way the point
cloud is sub sampled, but I don't know exactly what kind of relationship it
sets between the input and the output.
So, can anyone give me some advises regarding this subject? Basically, I
just need to align 58 point clouds that have, at this moment, different
number of points.
Any help is greatly appreciated!
Best regards,
Nuno
--
View this message in context: http://vtk.1045678.n5.nabble.com/Several-point-clouds-alignment-using-ICP-tp3395391p3409401.html
Sent from the VTK - Users mailing list archive at Nabble.com.
_______________________________________________
Powered by www.kitware.com
Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html
Please keep messages on-topic and check the VTK FAQ at: http://www.vtk.org/Wiki/VTK_FAQ
http://www.vtk.org/mailman/listinfo/vtkusers
--
Tim Hutton - http://www.sq3.org.uk - http://ferkeltongs.livejournal.com
nuno.jf
2011-03-04 15:45:53 UTC
Permalink
Hi Timm,

Thank you very much for you message!
Well, I know that each point cloud is rotated about 6.25 degrees in relation
to the previous point cloud. So,
I did this:

vtkTransformPolyDataFilter *TF = vtkTransformPolyDataFilter::New();
vtkTransform *ActualPosition = vtkTransform::New();

ActualPosition -> Identity();
ActualPosition -> PostMultiply();
ActualPosition -> Translate( 0, 0, -875); // bings the point cloud to
the origin
ActualPosition -> RotateY( 5 * 1.25 ); // rotates the point cloud
ActualPosition -> Translate( 0, 0, 875); // places the point cloud back
to where it was

TF -> SetInput( polyData2 );
TF -> SetTransform( ActualPosition );
TF -> Update();

I believe the surfaces have sufficient overlapping parts for ICP to work,
considering that each point cloud was obtained from the same equipment
scanning the object and rotating it 6.25 degrees between consecutive scans.
My ICP code is as follows:

vtkIterativeClosestPointTransform * icp =
vtkIterativeClosestPointTransform::New();

// Set SOURCE and TARGET points

icp -> SetTarget( polyData1 ); // I want to align polydata 2 with
polydata1
icp -> SetSource( TF -> GetOutput() ); // get polyData2 transformed as
described above


// Configure ICP transform
//---------------------------------------------------------

icp -> SetMaximumNumberOfIterations( 100 );
icp -> SetMaximumNumberOfLandmarks( 10000 );
icp -> StartByMatchingCentroidsOff();
icp -> GetLandmarkTransform()->SetModeToRigidBody();
icp -> SetMeanDistanceModeToRMS();
icp -> SetMaximumMeanDistance(0.000001);
icp -> Update();

std::cout << "ICP Mean Distance RMS = " << icp -> GetMeanDistance() <<
std::endl;

What should I do?
Thank you very much!
Best regards,

Nuno

--
View this message in context: http://vtk.1045678.n5.nabble.com/Several-point-clouds-alignment-using-ICP-tp3395391p3409677.html
Sent from the VTK - Users mailing list archive at Nabble.com.
Tim Hutton
2011-03-04 16:14:28 UTC
Permalink
I think you need to tell us more about your data source. Are you
scanning objects on a turntable with a fixed camera? If this is true
and you know the rotation step then you just need to work out the
rotation axis and you can align the scans directly. (Maybe scan a
calibration object first to compute the axis, that sort of thing.)
Post by nuno.jf
Hi Timm,
Thank you very much for you message!
Well, I know that each point cloud is rotated about 6.25 degrees in relation
to the previous point cloud. So,
vtkTransformPolyDataFilter *TF = vtkTransformPolyDataFilter::New();
               vtkTransform *ActualPosition = vtkTransform::New();
               ActualPosition -> Identity();
               ActualPosition -> PostMultiply();
               ActualPosition -> Translate( 0, 0, -875);                       // bings the point cloud to
the origin
               ActualPosition -> RotateY( 5 * 1.25 );                  // rotates the point cloud
               ActualPosition -> Translate( 0, 0,  875);                       // places the point cloud back
to where  it was
               TF -> SetInput( polyData2 );
               TF -> SetTransform( ActualPosition );
               TF -> Update();
I believe the surfaces have sufficient overlapping parts for ICP to work,
considering that each point cloud was obtained from the same equipment
scanning the object and rotating it 6.25 degrees between consecutive scans.
vtkIterativeClosestPointTransform * icp =
vtkIterativeClosestPointTransform::New();
               // Set SOURCE and TARGET points
               icp -> SetTarget( polyData1 );  // I want to align polydata 2 with
polydata1
               icp -> SetSource( TF -> GetOutput() ); // get polyData2 transformed as
described above
               // Configure ICP transform
               //---------------------------------------------------------
               icp -> SetMaximumNumberOfIterations( 100 );
               icp -> SetMaximumNumberOfLandmarks( 10000 );
               icp -> StartByMatchingCentroidsOff();
               icp -> GetLandmarkTransform()->SetModeToRigidBody();
               icp -> SetMeanDistanceModeToRMS();
               icp -> SetMaximumMeanDistance(0.000001);
               icp -> Update();
               std::cout << "ICP Mean Distance RMS = " << icp -> GetMeanDistance() <<
std::endl;
What should I do?
Thank you very much!
Best regards,
Nuno
--
View this message in context: http://vtk.1045678.n5.nabble.com/Several-point-clouds-alignment-using-ICP-tp3395391p3409677.html
Sent from the VTK - Users mailing list archive at Nabble.com.
_______________________________________________
Powered by www.kitware.com
Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html
Please keep messages on-topic and check the VTK FAQ at: http://www.vtk.org/Wiki/VTK_FAQ
http://www.vtk.org/mailman/listinfo/vtkusers
--
Tim Hutton - http://www.sq3.org.uk - http://ferkeltongs.livejournal.com
nuno.jf
2011-03-04 16:27:20 UTC
Permalink
The scanning object is placed on a rotating table. The light emitter(video
projector) and the detector (camera) have a fixed position outside the
rotating table. The rotation step corresponds to 6.25 degrees between
consecutive scans. The problem is that even applying this transformation
before ICP, I have a badly-aligned point cloud in the end.

--
View this message in context: http://vtk.1045678.n5.nabble.com/Several-point-clouds-alignment-using-ICP-tp3395391p3409741.html
Sent from the VTK - Users mailing list archive at Nabble.com.
Tim Hutton
2011-03-04 17:02:22 UTC
Permalink
That's odd.
nuno.jf
2011-03-14 10:38:06 UTC
Permalink
Sorry for the delay in my response. Well, this isn't a commercial machine, is
a prototype for a college project. I am rotating around the Y axis, and
translating according to the Z axis. I think I might have a problem with
the transformation in vtkTransformPolyDataFilter. My camera was located ~875
mm (according to Z axis) away from my camera. Between two consecutive steps
I have a rotation of the object of 6.25º (according to Y axis). I believe
the problem is that I don't consider the translation associated with the X
axis, and, when rotating the 10th image (for example) I have to rotate it
(10-1)*6.25 degrees, and in this case, it might produce a significant error.
For the calibration of my scanner I used Zhang's method with available
opencv libraries. After calibrating, I get a .xml file (cam_extrinsic.xml)
with the extrinsic parameters of the camera. The content of the file is the
following:

<?xml version="1.0"?>


2
3
f

-2.00187469e+000 -2.08160806e+000 -5.57140887e-001 -1.59499664e+002
-8.67975845e+001 8.86059509e+002


As the camera's extrinsic parameters stand for rotation and translation
relatively to my object, is there anyway I can get the correct distance and
rotation to apply to vtkTransformPolyDataFilter from this file?
Can anyone explain me what this numbers exactly are and mean?

That way I could define the correct translation and rotation.

vtkTransformPolyDataFilter *TF = vtkTransformPolyDataFilter::New();
vtkTransform *ActualPosition = vtkTransform::New();

ActualPosition -> Identity();
ActualPosition -> PostMultiply();
ActualPosition -> Translate( 0, 0, -875); // bings the 2º point cloud to
the origin
ActualPosition -> RotateY( 6.25 ); // rotates the 2º point cloud
ActualPosition -> Translate( 0, 0, 875); // places the 2º point cloud back
to where it was

TF -> SetInput( polyData2 );
TF -> SetTransform( ActualPosition );
TF -> Update();


--
View this message in context: http://vtk.1045678.n5.nabble.com/Several-point-clouds-alignment-using-ICP-tp3395391p3556104.html
Sent from the VTK - Users mailing list archive at Nabble.com.
nuno.jf
2011-03-14 10:44:27 UTC
Permalink
Please find the cam_extrinsic.xml with the html tags on it:

<?xml version="1.0"?>
< opencv_storage >

< rows > 2 < /rows >
< cols > 3 < /cols >
< dt > f < /dt >
< data >
-2.00187469e+000 -2.08160806e+000 -5.57140887e-001 -1.59499664e+002
-8.67975845e+001 8.86059509e+002
< /opencv_storage >





--
View this message in context: http://vtk.1045678.n5.nabble.com/Several-point-clouds-alignment-using-ICP-tp3395391p3556111.html
Sent from the VTK - Users mailing list archive at Nabble.com.

Wes Turner
2011-03-04 16:18:11 UTC
Permalink
Nuno,

For ICP, the issue is that every point you choose for the source point set
will feed into the calculation of the metric. If the clouds represent
different sections of the same part, and you choose points outside of the
overlap region, then the alignment will tend to increase the area of
overlap. Since you seem to have a good initial set for the alignment, I
would use this initial guess to estimate the area of overlap and then only
choose points from the source set that lie within that region.

- Wes
Post by nuno.jf
Hi Timm,
Thank you very much for you message!
Well, I know that each point cloud is rotated about 6.25 degrees in relation
to the previous point cloud. So,
vtkTransformPolyDataFilter *TF = vtkTransformPolyDataFilter::New();
vtkTransform *ActualPosition = vtkTransform::New();
ActualPosition -> Identity();
ActualPosition -> PostMultiply();
ActualPosition -> Translate( 0, 0, -875);
// bings the point cloud to
the origin
ActualPosition -> RotateY( 5 * 1.25 ); //
rotates the point cloud
ActualPosition -> Translate( 0, 0, 875);
// places the point cloud back
to where it was
TF -> SetInput( polyData2 );
TF -> SetTransform( ActualPosition );
TF -> Update();
I believe the surfaces have sufficient overlapping parts for ICP to work,
considering that each point cloud was obtained from the same equipment
scanning the object and rotating it 6.25 degrees between consecutive scans.
vtkIterativeClosestPointTransform * icp =
vtkIterativeClosestPointTransform::New();
// Set SOURCE and TARGET points
icp -> SetTarget( polyData1 ); // I want to align polydata 2 with
polydata1
icp -> SetSource( TF -> GetOutput() ); // get polyData2 transformed as
described above
// Configure ICP transform
//---------------------------------------------------------
icp -> SetMaximumNumberOfIterations( 100 );
icp -> SetMaximumNumberOfLandmarks( 10000 );
icp -> StartByMatchingCentroidsOff();
icp -> GetLandmarkTransform()->SetModeToRigidBody();
icp -> SetMeanDistanceModeToRMS();
icp -> SetMaximumMeanDistance(0.000001);
icp -> Update();
std::cout << "ICP Mean Distance RMS = " << icp -> GetMeanDistance() <<
std::endl;
What should I do?
Thank you very much!
Best regards,
Nuno
--
http://vtk.1045678.n5.nabble.com/Several-point-clouds-alignment-using-ICP-tp3395391p3409677.html
Sent from the VTK - Users mailing list archive at Nabble.com.
_______________________________________________
Powered by www.kitware.com
Visit other Kitware open-source projects at
http://www.kitware.com/opensource/opensource.html
http://www.vtk.org/Wiki/VTK_FAQ
http://www.vtk.org/mailman/listinfo/vtkusers
--
Wesley D. Turner, Ph.D.
Kitware, Inc.
Technical Leader
28 Corporate Drive
Clifton Park, NY 12065-8662
Phone: 518-881-4920
nuno.jf
2011-03-04 16:30:43 UTC
Permalink
Hi Wes,

Thank you very much for you message. My problem is that I don't know much
about ICP parameters and I don't know how to feed ICP only with the points
in the overlap region of both point clouds. Is there a basic way of doing
this?
Best regards,
Nuno

For ICP, the issue is that every point you choose for the source point set
will feed into the calculation of the metric. If the clouds represent
different sections of the same part, and you choose points outside of the
overlap region, then the alignment will tend to increase the area of
overlap. Since you seem to have a good initial set for the alignment, I
would use this initial guess to estimate the area of overlap and then only
choose points from the source set that lie within that region.

- Wes

--
View this message in context: http://vtk.1045678.n5.nabble.com/Several-point-clouds-alignment-using-ICP-tp3395391p3409746.html
Sent from the VTK - Users mailing list archive at Nabble.com.
Wes Turner
2011-03-04 17:54:51 UTC
Permalink
You can either clip based on a view frustrum, or using nearness constraints
after manually correcting for the rotation. Either should work. Make sure
you turn off the initial alignment of centroids on the PCA.

- Wes
Post by nuno.jf
Hi Wes,
Thank you very much for you message. My problem is that I don't know much
about ICP parameters and I don't know how to feed ICP only with the points
in the overlap region of both point clouds. Is there a basic way of doing
this?
Best regards,
Nuno
For ICP, the issue is that every point you choose for the source point set
will feed into the calculation of the metric. If the clouds represent
different sections of the same part, and you choose points outside of the
overlap region, then the alignment will tend to increase the area of
overlap. Since you seem to have a good initial set for the alignment, I
would use this initial guess to estimate the area of overlap and then only
choose points from the source set that lie within that region.
- Wes
--
http://vtk.1045678.n5.nabble.com/Several-point-clouds-alignment-using-ICP-tp3395391p3409746.html
Sent from the VTK - Users mailing list archive at Nabble.com.
_______________________________________________
Powered by www.kitware.com
Visit other Kitware open-source projects at
http://www.kitware.com/opensource/opensource.html
http://www.vtk.org/Wiki/VTK_FAQ
http://www.vtk.org/mailman/listinfo/vtkusers
--
Wesley D. Turner, Ph.D.
Kitware, Inc.
Technical Leader
28 Corporate Drive
Clifton Park, NY 12065-8662
Phone: 518-881-4920
Loading...