-
Notifications
You must be signed in to change notification settings - Fork 70
/
Copy pathGlobalRegistration.dox.cpp
89 lines (76 loc) · 3.05 KB
/
GlobalRegistration.dox.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#include <MRMesh/MRBox.h>
#include <MRMesh/MRMultiwayICP.h>
#include <MRMesh/MRPointCloud.h>
#include <MRMesh/MRPointsLoad.h>
#include <MRMesh/MRPointsSave.h>
#include <iostream>
void printStats( const MR::MultiwayICP& icp )
{
std::cout << "Samples: " << icp.getNumSamples() << std::endl
<< "Active point pairs: " << icp.getNumActivePairs() << std::endl;
if ( icp.getNumActivePairs() > 0 )
{
const auto p2ptMetric = icp.getMeanSqDistToPoint();
const auto p2plMetric = icp.getMeanSqDistToPlane();
std::cout << "RMS point-to-point distance: " << p2ptMetric << " ± " << icp.getMeanSqDistToPoint( p2ptMetric ) << std::endl
<< "RMS point-to-plane distance: " << p2plMetric << " ± " << icp.getMeanSqDistToPlane( p2plMetric ) << std::endl;
}
}
int main( int argc, char* argv[] )
{
if ( argc < 4 )
{
std::cerr << "Usage: " << argv[0] << " INPUT1 INPUT2 [INPUTS...] OUTPUT" << std::endl;
return EXIT_FAILURE;
}
// the global registration can be applied to meshes and point clouds
// to simplify the sample app, we will work with point clouds only
std::vector<MR::PointCloud> inputs;
// as ICP and MultiwayICP classes accept both meshes and point clouds,
// the input data must be converted to special wrapper objects
// NB: the wrapper objects hold *references* to the source data, NOT their copies
MR::ICPObjects objects;
MR::Box3f maxBBox;
for ( auto i = 1; i < argc - 1; ++i )
{
auto pointCloud = MR::PointsLoad::fromAnySupportedFormat( argv[i] );
if ( !pointCloud )
{
std::cerr << "Failed to load point cloud: " << pointCloud.error() << std::endl;
return EXIT_FAILURE;
}
auto bbox = pointCloud->computeBoundingBox();
if ( !maxBBox.valid() || bbox.volume() > maxBBox.volume() )
maxBBox = bbox;
inputs.emplace_back( std::move( *pointCloud ) );
// you may also set an affine transformation for each input as a second argument
objects.push_back( { inputs.back(), {} } );
}
// you can set various parameters for the global registration; see the documentation for more info
MR::MultiwayICP icp( objects, {
// set sampling voxel size
.samplingVoxelSize = maxBBox.diagonal() * 0.03f,
} );
icp.setParams( {} );
// gather statistics
icp.updateAllPointPairs();
printStats( icp );
std::cout << "Calculating transformations..." << std::endl;
auto xfs = icp.calculateTransformations();
printStats( icp );
MR::PointCloud output;
for ( auto i = MR::ObjId( 0 ); i < inputs.size(); ++i )
{
const auto& input = inputs[i];
const auto& xf = xfs[i];
for ( const auto& point : input.points )
output.points.emplace_back( xf( point ) );
}
auto res = MR::PointsSave::toAnySupportedFormat( output, argv[argc - 1] );
if ( !res )
{
std::cerr << "Failed to save point cloud: " << res.error() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}