8 #include "pipelines/registration/Registration.h"
21 namespace registration {
28 const Eigen::Matrix4d &transformation) {
40 double error2_private = 0.0;
43 #pragma omp for nowait
45 for (
int i = 0; i < (int)source.
size(); i++) {
46 std::vector<int> indices(1);
47 std::vector<double> dists(1);
50 1, indices, dists) > 0) {
51 error2_private += dists[0];
52 correspondence_set_private.push_back(
57 #pragma omp critical(GetRegistrationResultAndCorrespondences)
60 for (
int i = 0; i < (int)correspondence_set_private.size(); i++) {
61 result.correspondence_set_.push_back(
62 correspondence_set_private[i]);
64 error2 += error2_private;
70 if (
result.correspondence_set_.empty()) {
74 size_t corres_number =
result.correspondence_set_.size();
75 result.fitness_ = (double)corres_number / (
double)source.
size();
76 result.inlier_rmse_ = std::sqrt(error2 / (
double)corres_number);
86 const Eigen::Matrix4d &transformation) {
91 for (
const auto &c : corres) {
94 if (dis2 < max_dis2) {
97 result.correspondence_set_.push_back(c);
102 result.inlier_rmse_ = 0.0;
104 result.fitness_ = (double)good / (
double)corres.size();
105 result.inlier_rmse_ = std::sqrt(error2 / (
double)good);
113 const Eigen::Matrix4d &transformation
118 if (!transformation.isIdentity()) {
130 const Eigen::Matrix4d &init ,
144 "TransformationEstimationPointToPlane and "
145 "TransformationEstimationColoredICP "
146 "require pre-computed normal vectors.");
149 Eigen::Matrix4d transformation = init;
153 if (!init.isIdentity()) {
163 pcd, target,
result.correspondence_set_);
164 transformation = update * transformation;
188 const std::vector<std::reference_wrapper<const CorrespondenceChecker>>
193 if (ransac_n < 3 || (
int)corres.size() < ransac_n ||
207 unsigned int seed_val =
210 0,
static_cast<int>(corres.size()) - 1, seed_val);
213 #pragma omp for nowait
216 if (itr < exit_itr_local) {
217 for (
int j = 0; j < ransac_n; j++) {
218 ransac_corres[j] = corres[rand_generator()];
221 Eigen::Matrix4d transformation =
227 for (
const auto &checker : checkers) {
228 if (!checker.get().Check(source, target, ransac_corres,
234 if (!check)
continue;
242 if (
result.IsBetterRANSACThan(best_result_local)) {
243 best_result_local =
result;
248 std::log(1.0 - std::pow(
result.fitness_, ransac_n));
251 ?
static_cast<int>(
std::ceil(exit_itr_d))
258 #pragma omp critical(RegistrationRANSACBasedOnCorrespondence)
262 best_result = best_result_local;
264 if (exit_itr_local > exit_itr) {
265 exit_itr = exit_itr_local;
270 "RANSAC exits at {:d}-th iteration: inlier ratio {:e}, "
286 const std::vector<std::reference_wrapper<const CorrespondenceChecker>>
295 int num_src_pts = int(source.
size());
296 int num_tgt_pts = int(target.
size());
302 #pragma omp parallel for num_threads(utility::EstimateMaxThreads())
304 for (
int i = 0; i < num_src_pts; i++) {
305 std::vector<int> corres_tmp(1);
306 std::vector<double> dist_tmp(1);
308 kdtree_target.
SearchKNN(Eigen::VectorXd(source_feature.
data_.col(i)), 1,
309 corres_tmp, dist_tmp);
310 int j = corres_tmp[0];
320 #pragma omp parallel for num_threads(utility::EstimateMaxThreads())
322 for (
int j = 0; j < num_tgt_pts; ++j) {
323 std::vector<int> corres_tmp(1);
324 std::vector<double> dist_tmp(1);
326 Eigen::VectorXd(target_feature.
data_.col(j)), 1, corres_tmp,
328 int i = corres_tmp[0];
333 for (
int i = 0; i < num_src_pts; ++i) {
334 int j = corres_ij[i](1);
335 if (corres_ji[j](0) == i) {
336 corres_mutual.emplace_back(i, j);
341 if (
int(corres_mutual.size()) >= ransac_n * 3) {
343 corres_mutual.size());
346 estimation, ransac_n, checkers, criteria, seed);
349 "Too few correspondences after mutual filter, fall back to "
350 "original correspondences.");
355 ransac_n, checkers, criteria, seed);
362 const Eigen::Matrix4d &transformation) {
364 if (transformation.isIdentity() ==
false) {
384 #pragma omp for nowait
386 for (
int c = 0; c < int(
result.correspondence_set_.size()); c++) {
387 int t =
result.correspondence_set_[c](1);
391 G_r_private.setZero();
394 G_r_private(3) = 1.0;
395 GTG_private.noalias() += G_r_private * G_r_private.transpose();
396 G_r_private.setZero();
399 G_r_private(4) = 1.0;
400 GTG_private.noalias() += G_r_private * G_r_private.transpose();
401 G_r_private.setZero();
404 G_r_private(5) = 1.0;
405 GTG_private.noalias() += G_r_private * G_r_private.transpose();
408 #pragma omp critical(GetInformationMatrixFromPointClouds)
410 { GTG += GTG_private; }
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
virtual ccPointCloud & Transform(const Eigen::Matrix4d &trans) override
Apply transformation (4x4 matrix) to the geometry coordinates.
bool hasNormals() const override
Returns whether normals are enabled or not.
unsigned size() const override
Eigen::Vector3d getEigenPoint(size_t index) const
KDTree with FLANN for nearest neighbor search.
int SearchKNN(const T &query, int knn, std::vector< int > &indices, std::vector< double > &distance2) const
int SearchHybrid(const T &query, double radius, int max_nn, std::vector< int > &indices, std::vector< double > &distance2) const
bool SetGeometry(const ccHObject &geometry)
Class that defines the convergence criteria of ICP.
int max_iteration_
Maximum iteration before iteration stops.
Class that defines the convergence criteria of RANSAC.
int max_iteration_
Maximum iteration before iteration stops.
double confidence_
Desired probability of success.
double inlier_rmse_
RMSE of all inlier correspondences. Lower is better.
bool IsBetterRANSACThan(const RegistrationResult &other) const
Class to store featrues for registration.
Eigen::MatrixXd data_
Data buffer storing features.
constexpr bool has_value() const noexcept
constexpr T const & value() const &
__host__ __device__ int2 abs(int2 v)
Helper functions for the ml ops.
Eigen::Matrix< double, 6, 1 > Vector6d
Eigen::Matrix< double, 6, 6 > Matrix6d
Extending Eigen namespace by adding frequently used matrix type.
RegistrationResult RegistrationRANSACBasedOnCorrespondence(const ccPointCloud &source, const ccPointCloud &target, const CorrespondenceSet &corres, double max_correspondence_distance, const TransformationEstimation &estimation, int ransac_n, const std::vector< std::reference_wrapper< const CorrespondenceChecker >> &checkers, const RANSACConvergenceCriteria &criteria, utility::optional< unsigned int > seed)
Function for global RANSAC registration based on a given set of correspondences.
Eigen::Matrix6d GetInformationMatrixFromPointClouds(const ccPointCloud &source, const ccPointCloud &target, double max_correspondence_distance, const Eigen::Matrix4d &transformation)
std::vector< Eigen::Vector2i > CorrespondenceSet
RegistrationResult RegistrationICP(const ccPointCloud &source, const ccPointCloud &target, double max_correspondence_distance, const Eigen::Matrix4d &init, const TransformationEstimation &estimation, const ICPConvergenceCriteria &criteria)
Functions for ICP registration.
static RegistrationResult EvaluateRANSACBasedOnCorrespondence(const ccPointCloud &source, const ccPointCloud &target, const CorrespondenceSet &corres, double max_correspondence_distance, const Eigen::Matrix4d &transformation)
static RegistrationResult GetRegistrationResultAndCorrespondences(const ccPointCloud &source, const ccPointCloud &target, const geometry::KDTreeFlann &target_kdtree, double max_correspondence_distance, const Eigen::Matrix4d &transformation)
static const double max_correspondence_distance
RegistrationResult RegistrationRANSACBasedOnFeatureMatching(const ccPointCloud &source, const ccPointCloud &target, const utility::Feature &source_feature, const utility::Feature &target_feature, bool mutual_filter, double max_correspondence_distance, const TransformationEstimation &estimation, int ransac_n, const std::vector< std::reference_wrapper< const CorrespondenceChecker >> &checkers, const RANSACConvergenceCriteria &criteria, utility::optional< unsigned int > seed)
Function for global RANSAC registration based on feature matching.
RegistrationResult EvaluateRegistration(const ccPointCloud &source, const ccPointCloud &target, double max_correspondence_distance, const Eigen::Matrix4d &transformation)
Function for evaluating registration between point clouds.
MiniVec< float, N > ceil(const MiniVec< float, N > &a)
Generic file read and write utility for python interface.
Eigen::Matrix< Index, 2, 1 > Vector2i