template <typename PointSource, typename PointTarget> void pcl::registration::CorrespondenceEstimation<PointSource, PointTarget>::determineReciprocalCorrespondences ( pcl::Correspondences &correspondences) { typedef typename pcl::traits::fieldList<PointSource>::type FieldListSource; typedef typename pcl::traits::fieldList<PointTarget>::type FieldListTarget; typedef typename pcl::intersect<FieldListSource, FieldListTarget>::type FieldList; if (!initCompute ()) return; if (!target_) { PCL_WARN ("[pcl::%s::compute] No input target dataset was given!\n", getClassName ().c_str ()); return; } // setup tree for reciprocal search pcl::KdTreeFLANN<PointSource> tree_reciprocal; tree_reciprocal.setInputCloud (input_, indices_); correspondences.resize (indices_->size()); std::vector<int> index (1); std::vector<float> distance (1); std::vector<int> index_reciprocal (1); std::vector<float> distance_reciprocal (1); pcl::Correspondence corr; unsigned int nr_valid_correspondences = 0; for (size_t i = 0; i < indices_->size (); ++i) { // Copy the source data to a target PointTarget format so we can search in the tree PointTarget pt_src; pcl::for_each_type <FieldList> (pcl::NdConcatenateFunctor <PointSource, PointTarget> ( input_->points[(*indices_)[i]], pt_src)); //tree_->nearestKSearch (input_->points[(*indices_)[i]], 1, index, distance); tree_->nearestKSearch (pt_src, 1, index, distance); // Copy the target data to a target PointSource format so we can search in the tree_reciprocal PointSource pt_tgt; pcl::for_each_type <FieldList> (pcl::NdConcatenateFunctor <PointTarget, PointSource> ( target_->points[index[0]], pt_tgt)); //tree_reciprocal.nearestKSearch (target_->points[index[0]], 1, index_reciprocal, distance_reciprocal); tree_reciprocal.nearestKSearch (pt_tgt, 1, index_reciprocal, distance_reciprocal); if ((*indices_)[i] == index_reciprocal[0]) { corr.index_query = (*indices_)[i]; corr.index_match = index[0]; corr.distance = distance[0]; correspondences[nr_valid_correspondences] = corr; ++nr_valid_correspondences; } } correspondences.resize (nr_valid_correspondences); deinitCompute (); }
template <typename PointSource, typename PointTarget, typename Scalar> void pcl::registration::CorrespondenceEstimation<PointSource, PointTarget, Scalar>::determineReciprocalCorrespondences ( pcl::Correspondences &correspondences, double max_distance) { if (!initCompute ()) return; typedef typename pcl::traits::fieldList<PointSource>::type FieldListSource; typedef typename pcl::traits::fieldList<PointTarget>::type FieldListTarget; typedef typename pcl::intersect<FieldListSource, FieldListTarget>::type FieldList; // setup tree for reciprocal search pcl::KdTreeFLANN<PointSource> tree_reciprocal; // Set the internal point representation of choice if (point_representation_) tree_reciprocal.setPointRepresentation (point_representation_); tree_reciprocal.setInputCloud (input_, indices_); double max_dist_sqr = max_distance * max_distance; correspondences.resize (indices_->size()); std::vector<int> index (1); std::vector<float> distance (1); std::vector<int> index_reciprocal (1); std::vector<float> distance_reciprocal (1); pcl::Correspondence corr; unsigned int nr_valid_correspondences = 0; int target_idx = 0; // Check if the template types are the same. If true, avoid a copy. // Both point types MUST be registered using the POINT_CLOUD_REGISTER_POINT_STRUCT macro! if (isSamePointType<PointSource, PointTarget> ()) { // Iterate over the input set of source indices for (std::vector<int>::const_iterator idx = indices_->begin (); idx != indices_->end (); ++idx) { tree_->nearestKSearch (input_->points[*idx], 1, index, distance); if (distance[0] > max_dist_sqr) continue; target_idx = index[0]; tree_reciprocal.nearestKSearch (target_->points[target_idx], 1, index_reciprocal, distance_reciprocal); if (distance_reciprocal[0] > max_dist_sqr || *idx != index_reciprocal[0]) continue; corr.index_query = *idx; corr.index_match = index[0]; corr.distance = distance[0]; correspondences[nr_valid_correspondences++] = corr; } } else { PointTarget pt_src; PointSource pt_tgt; // Iterate over the input set of source indices for (std::vector<int>::const_iterator idx = indices_->begin (); idx != indices_->end (); ++idx) { // Copy the source data to a target PointTarget format so we can search in the tree pcl::for_each_type <FieldList> (pcl::NdConcatenateFunctor <PointSource, PointTarget> ( input_->points[*idx], pt_src)); tree_->nearestKSearch (pt_src, 1, index, distance); if (distance[0] > max_dist_sqr) continue; target_idx = index[0]; // Copy the target data to a target PointSource format so we can search in the tree_reciprocal pcl::for_each_type<FieldList> (pcl::NdConcatenateFunctor <PointTarget, PointSource> ( target_->points[target_idx], pt_tgt)); tree_reciprocal.nearestKSearch (pt_tgt, 1, index_reciprocal, distance_reciprocal); if (distance_reciprocal[0] > max_dist_sqr || *idx != index_reciprocal[0]) continue; corr.index_query = *idx; corr.index_match = index[0]; corr.distance = distance[0]; correspondences[nr_valid_correspondences++] = corr; } } correspondences.resize (nr_valid_correspondences); deinitCompute (); }
template <typename PointSource, typename PointTarget, typename NormalT> void pcl::registration::CorrespondenceEstimationBackProjection<PointSource, PointTarget, NormalT>::determineReciprocalCorrespondences ( pcl::Correspondences &correspondences, double max_distance) { if (!initCompute ()) return; typedef typename pcl::traits::fieldList<PointSource>::type FieldListSource; typedef typename pcl::traits::fieldList<PointTarget>::type FieldListTarget; typedef typename pcl::intersect<FieldListSource, FieldListTarget>::type FieldList; // setup tree for reciprocal search pcl::KdTreeFLANN<PointSource> tree_reciprocal; // Set the internal point representation of choice if (point_representation_) tree_reciprocal.setPointRepresentation (point_representation_); tree_reciprocal.setInputCloud (input_, indices_); correspondences.resize (indices_->size ()); std::vector<int> nn_indices (k_); std::vector<float> nn_dists (k_); std::vector<int> index_reciprocal (1); std::vector<float> distance_reciprocal (1); float min_dist = std::numeric_limits<float>::max (); int min_index = 0; pcl::Correspondence corr; unsigned int nr_valid_correspondences = 0; int target_idx = 0; // Check if the template types are the same. If true, avoid a copy. // Both point types MUST be registered using the POINT_CLOUD_REGISTER_POINT_STRUCT macro! if (isSamePointType<PointSource, PointTarget> ()) { PointTarget pt; // Iterate over the input set of source indices for (std::vector<int>::const_iterator idx_i = indices_->begin (); idx_i != indices_->end (); ++idx_i) { tree_->nearestKSearch (input_->points[*idx_i], k_, nn_indices, nn_dists); // Among the K nearest neighbours find the one with minimum perpendicular distance to the normal min_dist = std::numeric_limits<float>::max (); // Find the best correspondence for (size_t j = 0; j < nn_indices.size (); j++) { float cos_angle = source_normals_->points[*idx_i].normal_x * target_normals_->points[nn_indices[j]].normal_x + source_normals_->points[*idx_i].normal_y * target_normals_->points[nn_indices[j]].normal_y + source_normals_->points[*idx_i].normal_z * target_normals_->points[nn_indices[j]].normal_z ; float dist = nn_dists[min_index] * (2.0f - cos_angle * cos_angle); if (dist < min_dist) { min_dist = dist; min_index = j; } } if (min_dist > max_distance) continue; // Check if the correspondence is reciprocal if (target_indices_) target_idx = (*target_indices_)[nn_indices[min_index]]; else target_idx = nn_indices[min_index]; tree_reciprocal.nearestKSearch (target_->points[target_idx], 1, index_reciprocal, distance_reciprocal); if (*idx_i != index_reciprocal[0]) continue; corr.index_query = *idx_i; corr.index_match = nn_indices[min_index]; corr.distance = nn_dists[min_index];//min_dist; correspondences[nr_valid_correspondences++] = corr; } } else { PointTarget pt; // Iterate over the input set of source indices for (std::vector<int>::const_iterator idx_i = indices_->begin (); idx_i != indices_->end (); ++idx_i) { tree_->nearestKSearch (input_->points[*idx_i], k_, nn_indices, nn_dists); // Among the K nearest neighbours find the one with minimum perpendicular distance to the normal min_dist = std::numeric_limits<float>::max (); // Find the best correspondence for (size_t j = 0; j < nn_indices.size (); j++) { PointSource pt_src; // Copy the source data to a target PointTarget format so we can search in the tree pcl::for_each_type <FieldListTarget> (pcl::NdConcatenateFunctor <PointSource, PointTarget> ( input_->points[*idx_i], pt_src)); float cos_angle = source_normals_->points[*idx_i].normal_x * target_normals_->points[nn_indices[j]].normal_x + source_normals_->points[*idx_i].normal_y * target_normals_->points[nn_indices[j]].normal_y + source_normals_->points[*idx_i].normal_z * target_normals_->points[nn_indices[j]].normal_z ; float dist = nn_dists[min_index] * (2.0f - cos_angle * cos_angle); if (dist < min_dist) { min_dist = dist; min_index = j; } } if (min_dist > max_distance) continue; // Check if the correspondence is reciprocal if (target_indices_) target_idx = (*target_indices_)[nn_indices[min_index]]; else target_idx = nn_indices[min_index]; tree_reciprocal.nearestKSearch (target_->points[target_idx], 1, index_reciprocal, distance_reciprocal); if (*idx_i != index_reciprocal[0]) continue; corr.index_query = *idx_i; corr.index_match = nn_indices[min_index]; corr.distance = nn_dists[min_index];//min_dist; correspondences[nr_valid_correspondences++] = corr; } } correspondences.resize (nr_valid_correspondences); deinitCompute (); }
template <typename PointSource, typename PointTarget, typename NormalT, typename Scalar> void pcl::registration::CorrespondenceEstimationNormalShooting<PointSource, PointTarget, NormalT, Scalar>::determineReciprocalCorrespondences ( pcl::Correspondences &correspondences, double max_distance) { if (!initCompute ()) return; typedef typename pcl::traits::fieldList<PointSource>::type FieldListSource; typedef typename pcl::traits::fieldList<PointTarget>::type FieldListTarget; typedef typename pcl::intersect<FieldListSource, FieldListTarget>::type FieldList; // setup tree for reciprocal search // Set the internal point representation of choice if (!initComputeReciprocal ()) return; correspondences.resize (indices_->size ()); std::vector<int> nn_indices (k_); std::vector<float> nn_dists (k_); std::vector<int> index_reciprocal (1); std::vector<float> distance_reciprocal (1); double min_dist = std::numeric_limits<double>::max (); int min_index = 0; pcl::Correspondence corr; unsigned int nr_valid_correspondences = 0; int target_idx = 0; // Check if the template types are the same. If true, avoid a copy. // Both point types MUST be registered using the POINT_CLOUD_REGISTER_POINT_STRUCT macro! if (isSamePointType<PointSource, PointTarget> ()) { PointTarget pt; // Iterate over the input set of source indices for (std::vector<int>::const_iterator idx_i = indices_->begin (); idx_i != indices_->end (); ++idx_i) { tree_->nearestKSearch (input_->points[*idx_i], k_, nn_indices, nn_dists); // Among the K nearest neighbours find the one with minimum perpendicular distance to the normal min_dist = std::numeric_limits<double>::max (); // Find the best correspondence for (size_t j = 0; j < nn_indices.size (); j++) { // computing the distance between a point and a line in 3d. // Reference - http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html pt.x = target_->points[nn_indices[j]].x - input_->points[*idx_i].x; pt.y = target_->points[nn_indices[j]].y - input_->points[*idx_i].y; pt.z = target_->points[nn_indices[j]].z - input_->points[*idx_i].z; const NormalT &normal = source_normals_->points[*idx_i]; Eigen::Vector3d N (normal.normal_x, normal.normal_y, normal.normal_z); Eigen::Vector3d V (pt.x, pt.y, pt.z); Eigen::Vector3d C = N.cross (V); // Check if we have a better correspondence double dist = C.dot (C); if (dist < min_dist) { min_dist = dist; min_index = static_cast<int> (j); } } if (min_dist > max_distance) continue; // Check if the correspondence is reciprocal target_idx = nn_indices[min_index]; tree_reciprocal_->nearestKSearch (target_->points[target_idx], 1, index_reciprocal, distance_reciprocal); if (*idx_i != index_reciprocal[0]) continue; // Correspondence IS reciprocal, save it and continue corr.index_query = *idx_i; corr.index_match = nn_indices[min_index]; corr.distance = nn_dists[min_index];//min_dist; correspondences[nr_valid_correspondences++] = corr; } } else { PointTarget pt; // Iterate over the input set of source indices for (std::vector<int>::const_iterator idx_i = indices_->begin (); idx_i != indices_->end (); ++idx_i) { tree_->nearestKSearch (input_->points[*idx_i], k_, nn_indices, nn_dists); // Among the K nearest neighbours find the one with minimum perpendicular distance to the normal min_dist = std::numeric_limits<double>::max (); // Find the best correspondence for (size_t j = 0; j < nn_indices.size (); j++) { PointSource pt_src; // Copy the source data to a target PointTarget format so we can search in the tree pcl::for_each_type <FieldListTarget> (pcl::NdConcatenateFunctor <PointSource, PointTarget> ( input_->points[*idx_i], pt_src)); // computing the distance between a point and a line in 3d. // Reference - http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html pt.x = target_->points[nn_indices[j]].x - pt_src.x; pt.y = target_->points[nn_indices[j]].y - pt_src.y; pt.z = target_->points[nn_indices[j]].z - pt_src.z; const NormalT &normal = source_normals_->points[*idx_i]; Eigen::Vector3d N (normal.normal_x, normal.normal_y, normal.normal_z); Eigen::Vector3d V (pt.x, pt.y, pt.z); Eigen::Vector3d C = N.cross (V); // Check if we have a better correspondence double dist = C.dot (C); if (dist < min_dist) { min_dist = dist; min_index = static_cast<int> (j); } } if (min_dist > max_distance) continue; // Check if the correspondence is reciprocal target_idx = nn_indices[min_index]; tree_reciprocal_->nearestKSearch (target_->points[target_idx], 1, index_reciprocal, distance_reciprocal); if (*idx_i != index_reciprocal[0]) continue; // Correspondence IS reciprocal, save it and continue corr.index_query = *idx_i; corr.index_match = nn_indices[min_index]; corr.distance = nn_dists[min_index];//min_dist; correspondences[nr_valid_correspondences++] = corr; } } correspondences.resize (nr_valid_correspondences); deinitCompute (); }