added support for GenericDescriptorOutlierFilter to the CGAL libpointmatcher interface

This commit is contained in:
Dmitry Anisimov 2021-04-29 15:23:38 +02:00
parent 9e1a4e7037
commit c8307dc0d6
4 changed files with 84 additions and 11 deletions

View File

@ -435,6 +435,30 @@ CGAL_DEF_GET_INITIALIZED_INDEX_MAP(face, typename boost::graph_traits<Graph>::fa
> ::type type; > ::type type;
}; };
template<typename PointRange, typename NamedParameters>
class GetScalarMap
{
struct DummyScalarMap
{
typedef typename std::iterator_traits<typename PointRange::iterator>::value_type key_type;
typedef typename GetK<PointRange, NamedParameters>::Kernel::FT value_type;
typedef value_type reference;
typedef boost::read_write_property_map_tag category;
typedef DummyScalarMap Self;
friend reference get(const Self&, const key_type&) { return value_type(1); }
friend void put(const Self&, const key_type&, const value_type&) { }
};
public:
typedef DummyScalarMap NoMap;
typedef typename internal_np::Lookup_named_param_def <
internal_np::scalar_t,
NamedParameters,
DummyScalarMap // default
> ::type type;
};
template<typename PlaneRange, typename NamedParameters> template<typename PlaneRange, typename NamedParameters>
class GetPlaneMap class GetPlaneMap
{ {

View File

@ -174,6 +174,7 @@ CGAL_add_named_parameter(pointmatcher_config_t, pointmatcher_config, pointmatche
CGAL_add_named_parameter(adjacencies_t, adjacencies, adjacencies) CGAL_add_named_parameter(adjacencies_t, adjacencies, adjacencies)
CGAL_add_named_parameter(scan_angle_t, scan_angle_map, scan_angle_map) CGAL_add_named_parameter(scan_angle_t, scan_angle_map, scan_angle_map)
CGAL_add_named_parameter(scanline_id_t, scanline_id_map, scanline_id_map) CGAL_add_named_parameter(scanline_id_t, scanline_id_map, scanline_id_map)
CGAL_add_named_parameter(scalar_t, scalar_map, scalar_map)
// List of named parameters used in Surface_mesh_approximation package // List of named parameters used in Surface_mesh_approximation package
CGAL_add_named_parameter(verbose_level_t, verbose_level, verbose_level) CGAL_add_named_parameter(verbose_level_t, verbose_level, verbose_level)

View File

@ -21,6 +21,17 @@ typedef std::pair<Point_3, Vector_3> Pwn;
typedef CGAL::First_of_pair_property_map<Pwn> Point_map; typedef CGAL::First_of_pair_property_map<Pwn> Point_map;
typedef CGAL::Second_of_pair_property_map<Pwn> Normal_map; typedef CGAL::Second_of_pair_property_map<Pwn> Normal_map;
struct Weight_map
{
typedef Pwn key_type;
typedef typename K::FT value_type;
typedef value_type reference;
typedef boost::readable_property_map_tag category;
typedef Weight_map Self;
friend reference get(const Self&, const key_type&) { return value_type(1); }
};
namespace params = CGAL::parameters; namespace params = CGAL::parameters;
int main(int argc, const char** argv) int main(int argc, const char** argv)
@ -69,6 +80,7 @@ int main(int argc, const char** argv)
// Prepare outlier filters // Prepare outlier filters
std::vector<ICP_config> outlier_filters; std::vector<ICP_config> outlier_filters;
outlier_filters.push_back( ICP_config { /*.name=*/"TrimmedDistOutlierFilter", /*.params=*/{ {"ratio", "0.75" }} } ); outlier_filters.push_back( ICP_config { /*.name=*/"TrimmedDistOutlierFilter", /*.params=*/{ {"ratio", "0.75" }} } );
outlier_filters.push_back( ICP_config { /*.name=*/"GenericDescriptorOutlierFilter", /*.params=*/{ {"descName", "weights" }} } );
// Prepare error minimizer // Prepare error minimizer
ICP_config error_minimizer { /*.name=*/"PointToPointErrorMinimizer"}; ICP_config error_minimizer { /*.name=*/"PointToPointErrorMinimizer"};
@ -92,7 +104,7 @@ int main(int argc, const char** argv)
std::pair<K::Aff_transformation_3, bool> res = std::pair<K::Aff_transformation_3, bool> res =
CGAL::pointmatcher::compute_registration_transformation CGAL::pointmatcher::compute_registration_transformation
(pwns1, pwns2, (pwns1, pwns2,
params::point_map(Point_map()).normal_map(Normal_map()) params::point_map(Point_map()).normal_map(Normal_map()).scalar_map(Weight_map())
.point_set_filters(point_set_1_filters) .point_set_filters(point_set_1_filters)
.matcher(matcher) .matcher(matcher)
.outlier_filters(outlier_filters) .outlier_filters(outlier_filters)
@ -100,7 +112,7 @@ int main(int argc, const char** argv)
.transformation_checkers(transformation_checkers) .transformation_checkers(transformation_checkers)
.inspector(inspector) .inspector(inspector)
.logger(logger), .logger(logger),
params::point_map(Point_map()).normal_map(Normal_map()) params::point_map(Point_map()).normal_map(Normal_map()).scalar_map(Weight_map())
.point_set_filters(point_set_2_filters) .point_set_filters(point_set_2_filters)
.transformation(identity_transform) /* initial transform for pwns2. .transformation(identity_transform) /* initial transform for pwns2.
* default value is already identity transform. * default value is already identity transform.

View File

@ -220,10 +220,11 @@ template<typename Scalar,
typename PointRange, typename PointRange,
typename PointMap, typename PointMap,
typename VectorMap, typename VectorMap,
typename ScalarMap,
typename PM_matrix> typename PM_matrix>
void void
copy_cgal_points_to_pm_matrix copy_cgal_points_to_pm_matrix
(const PointRange& prange, PointMap point_map, VectorMap vector_map, PM_matrix& pm_points, PM_matrix& pm_normals) (const PointRange& prange, PointMap point_map, VectorMap vector_map, ScalarMap scalar_map, PM_matrix& pm_points, PM_matrix& pm_normals, PM_matrix& pm_weights)
{ {
int idx = 0; int idx = 0;
for(const auto& p : prange) for(const auto& p : prange)
@ -241,6 +242,10 @@ copy_cgal_points_to_pm_matrix
pm_normals(1, idx) = normal.y(); pm_normals(1, idx) = normal.y();
pm_normals(2, idx) = normal.z(); pm_normals(2, idx) = normal.z();
// weight
const auto& weight = get(scalar_map, p);
pm_weights(0, idx) = weight;
++idx; ++idx;
} }
} }
@ -251,11 +256,14 @@ template <class Kernel,
class PointMap1, class PointMap1,
class PointMap2, class PointMap2,
class VectorMap1, class VectorMap1,
class VectorMap2> class VectorMap2,
class ScalarMap1,
class ScalarMap2>
std::pair<typename Kernel::Aff_transformation_3, bool> std::pair<typename Kernel::Aff_transformation_3, bool>
compute_registration_transformation(const PointRange1& range1, const PointRange2& range2, compute_registration_transformation(const PointRange1& range1, const PointRange2& range2,
PointMap1 point_map1, PointMap2 point_map2, PointMap1 point_map1, PointMap2 point_map2,
VectorMap1 vector_map1, VectorMap2 vector_map2, VectorMap1 vector_map1, VectorMap2 vector_map2,
ScalarMap1 scalar_map1, ScalarMap2 scalar_map2,
const typename Kernel::Aff_transformation_3& initial_transform, const typename Kernel::Aff_transformation_3& initial_transform,
ICP<typename Kernel::FT> icp) ICP<typename Kernel::FT> icp)
{ {
@ -273,8 +281,10 @@ compute_registration_transformation(const PointRange1& range1, const PointRange2
PM_matrix ref_points_pos_matrix = PM_matrix (4, nb_ref_points); PM_matrix ref_points_pos_matrix = PM_matrix (4, nb_ref_points);
PM_matrix ref_points_normal_matrix = PM_matrix (3, nb_ref_points); PM_matrix ref_points_normal_matrix = PM_matrix (3, nb_ref_points);
PM_matrix ref_points_weight_matrix = PM_matrix (1, nb_ref_points);
PM_matrix points_pos_matrix = PM_matrix (4, nb_points); PM_matrix points_pos_matrix = PM_matrix (4, nb_points);
PM_matrix points_normal_matrix = PM_matrix (3, nb_points); PM_matrix points_normal_matrix = PM_matrix (3, nb_points);
PM_matrix points_weight_matrix = PM_matrix (1, nb_points);
// In CGAL, point_set_1 is the reference while point_set_2 is the data // In CGAL, point_set_1 is the reference while point_set_2 is the data
@ -282,16 +292,20 @@ compute_registration_transformation(const PointRange1& range1, const PointRange2
internal::copy_cgal_points_to_pm_matrix<Scalar>(range1, internal::copy_cgal_points_to_pm_matrix<Scalar>(range1,
point_map1, point_map1,
vector_map1, vector_map1,
scalar_map1,
ref_points_pos_matrix, // out ref_points_pos_matrix, // out
ref_points_normal_matrix); // out ref_points_normal_matrix, // out
ref_points_weight_matrix); // out
internal::copy_cgal_points_to_pm_matrix<Scalar>(range2, internal::copy_cgal_points_to_pm_matrix<Scalar>(range2,
point_map2, point_map2,
vector_map2, vector_map2,
scalar_map2,
points_pos_matrix, // out points_pos_matrix, // out
points_normal_matrix); // out points_normal_matrix, // out
points_weight_matrix); // out
auto construct_PM_cloud = [](const PM_matrix& positions, const PM_matrix& normals) -> PM_cloud auto construct_PM_cloud = [](const PM_matrix& positions, const PM_matrix& normals, const PM_matrix& weights) -> PM_cloud
{ {
PM_cloud cloud; PM_cloud cloud;
@ -300,12 +314,13 @@ compute_registration_transformation(const PointRange1& range1, const PointRange2
cloud.addFeature("z", positions.row(2)); cloud.addFeature("z", positions.row(2));
cloud.addFeature("pad", positions.row(3)); cloud.addFeature("pad", positions.row(3));
cloud.addDescriptor("normals", normals); cloud.addDescriptor("normals", normals);
cloud.addDescriptor("weights", weights);
return cloud; return cloud;
}; };
PM_cloud ref_cloud = construct_PM_cloud(ref_points_pos_matrix, ref_points_normal_matrix); PM_cloud ref_cloud = construct_PM_cloud(ref_points_pos_matrix, ref_points_normal_matrix, ref_points_weight_matrix);
PM_cloud cloud = construct_PM_cloud(points_pos_matrix, points_normal_matrix); PM_cloud cloud = construct_PM_cloud(points_pos_matrix, points_normal_matrix, points_weight_matrix);
PM_transform_params pm_transform_params = PM_transform_params::Identity(4,4); PM_transform_params pm_transform_params = PM_transform_params::Identity(4,4);
@ -385,6 +400,12 @@ compute_registration_transformation(const PointRange1& range1, const PointRange2
of the iterator of `PointRange1` and whose value type is `geom_traits::Vector_3`} of the iterator of `PointRange1` and whose value type is `geom_traits::Vector_3`}
\cgalParamNEnd \cgalParamNEnd
\cgalParamNBegin{scalar_map}
\cgalParamDescription{a property map associating 1D values - scalars to the elements of the point set `point_set_1`}
\cgalParamType{a model of `ReadablePropertyMap` whose key type is the value type
of the iterator of `PointRange1` and whose value type is `geom_traits::FT`}
\cgalParamNEnd
\cgalParamNBegin{point_set_filters} \cgalParamNBegin{point_set_filters}
\cgalParamDescription{a chain of filters to be applied to the point set} \cgalParamDescription{a chain of filters to be applied to the point set}
\cgalParamType{a class model of `Range`. The value type of its iterator must be `ICP_config`.} \cgalParamType{a class model of `Range`. The value type of its iterator must be `ICP_config`.}
@ -510,6 +531,12 @@ compute_registration_transformation(const PointRange1& range1, const PointRange2
of the iterator of `PointRange2` and whose value type is `geom_traits::Vector_3`} of the iterator of `PointRange2` and whose value type is `geom_traits::Vector_3`}
\cgalParamNEnd \cgalParamNEnd
\cgalParamNBegin{scalar_map}
\cgalParamDescription{a property map associating 1D values - scalars to the elements of the point set `point_set_2`}
\cgalParamType{a model of `ReadablePropertyMap` whose key type is the value type
of the iterator of `PointRange2` and whose value type is `geom_traits::FT`}
\cgalParamNEnd
\cgalParamNBegin{point_set_filters} \cgalParamNBegin{point_set_filters}
\cgalParamDescription{a chain of filters to be applied to the point set} \cgalParamDescription{a chain of filters to be applied to the point set}
\cgalParamType{a class model of `Range`. The value type of its iterator must be `ICP_config`.} \cgalParamType{a class model of `Range`. The value type of its iterator must be `ICP_config`.}
@ -576,14 +603,22 @@ compute_registration_transformation (const PointRange1& point_set_1, const Point
typename boost::property_traits<NormalMap2>::value_type> ::value), typename boost::property_traits<NormalMap2>::value_type> ::value),
"The vector type of input ranges must be the same"); "The vector type of input ranges must be the same");
typedef typename PSP::GetScalarMap<PointRange1, NamedParameters1>::type WeightMap1;
typedef typename PSP::GetScalarMap<PointRange2, NamedParameters2>::type WeightMap2;
CGAL_static_assertion_msg((boost::is_same< typename boost::property_traits<WeightMap1>::value_type,
typename boost::property_traits<WeightMap2>::value_type> ::value),
"The scalar type of input ranges must be the same");
typedef typename PSP::GetK<PointRange1, NamedParameters1>::Kernel Kernel; typedef typename PSP::GetK<PointRange1, NamedParameters1>::Kernel Kernel;
typedef typename Kernel::FT Scalar; typedef typename Kernel::FT Scalar;
typedef typename Kernel::Aff_transformation_3 Transformation; typedef typename Kernel::Aff_transformation_3 Transformation;
PointMap1 point_map1 = choose_parameter(get_parameter(np1, internal_np::point_map), PointMap1()); PointMap1 point_map1 = choose_parameter(get_parameter(np1, internal_np::point_map), PointMap1());
NormalMap1 normal_map1 = choose_parameter(get_parameter(np1, internal_np::normal_map), NormalMap1()); NormalMap1 normal_map1 = choose_parameter(get_parameter(np1, internal_np::normal_map), NormalMap1());
WeightMap1 weight_map1 = choose_parameter(get_parameter(np1, internal_np::scalar_map), WeightMap1());
PointMap2 point_map2 = choose_parameter(get_parameter(np2, internal_np::point_map), PointMap2()); PointMap2 point_map2 = choose_parameter(get_parameter(np2, internal_np::point_map), PointMap2());
NormalMap2 normal_map2 = choose_parameter(get_parameter(np2, internal_np::normal_map), NormalMap2()); NormalMap2 normal_map2 = choose_parameter(get_parameter(np2, internal_np::normal_map), NormalMap2());
WeightMap2 weight_map2 = choose_parameter(get_parameter(np2, internal_np::scalar_map), WeightMap2());
// initial transformation // initial transformation
Transformation initial_transformation Transformation initial_transformation
@ -592,6 +627,7 @@ compute_registration_transformation (const PointRange1& point_set_1, const Point
return internal::compute_registration_transformation<Kernel>(point_set_1, point_set_2, return internal::compute_registration_transformation<Kernel>(point_set_1, point_set_2,
point_map1, point_map2, point_map1, point_map2,
normal_map1, normal_map2, normal_map1, normal_map2,
weight_map1, weight_map2,
initial_transformation, initial_transformation,
internal::construct_icp<Scalar>(np1, np2)); internal::construct_icp<Scalar>(np1, np2));
} }