如何在PCL配准中使用kd-Tree以外的搜索方法?
基于PCL有序点云使用OrganizedNeighbor实现配准对应估计的可行方案
针对有序点云场景下,想替换PCL配准模块默认的kd-Tree为OrganizedNeighbor搜索方法的需求,有两种可行实现方案:
方案一:自定义适配OrganizedNeighbor的CorrespondenceEstimation子类
PCL的CorrespondenceEstimation类默认依赖kd-Tree,但可以通过继承并重写核心方法来适配OrganizedNeighbor。核心思路是替换内部的搜索对象,同时处理setPointRepresentation这个仅kd-Tree支持的方法:
- 定义子类继承自
pcl::CorrespondenceEstimation<PointT, PointT> - 内部维护
pcl::OrganizedNeighbor<PointT>对象替代原有的kd-Tree - 重写
setInputTarget、computeCorrespondences等方法,调用OrganizedNeighbor的接口 - 重写
setPointRepresentation方法,直接抛出异常或忽略(因为OrganizedNeighbor不支持该功能)
示例代码片段:
#include <pcl/registration/correspondence_estimation.h> #include <pcl/search/organized.h> template <typename PointT> class CorrespondenceEstimationOrganized : public pcl::CorrespondenceEstimation<PointT, PointT> { public: using Ptr = boost::shared_ptr<CorrespondenceEstimationOrganized<PointT>>; using ConstPtr = boost::shared_ptr<const CorrespondenceEstimationOrganized<PointT>>; void setInputTarget(const typename pcl::PointCloud<PointT>::ConstPtr &target) override { target_ = target; tree_->setInputCloud(target); } void computeCorrespondences(pcl::Correspondences &correspondences, double max_distance = std::numeric_limits<double>::max()) override { correspondences.resize(source_->size()); for (size_t i = 0; i < source_->size(); ++i) { std::vector<int> indices(1); std::vector<float> distances(1); tree_->nearestKSearch((*source_)[i], 1, indices, distances); if (distances[0] <= max_distance) { correspondences[i].index_query = static_cast<int>(i); correspondences[i].index_match = indices[0]; correspondences[i].distance = distances[0]; } else { correspondences[i].index_query = static_cast<int>(i); correspondences[i].index_match = -1; } } } // 重写setPointRepresentation,因为OrganizedNeighbor不支持该功能 void setPointRepresentation(const typename pcl::PointRepresentation<PointT>::ConstPtr &) override { throw std::runtime_error("OrganizedNeighbor does not support PointRepresentation"); } private: typename pcl::OrganizedNeighbor<PointT>::Ptr tree_{new pcl::OrganizedNeighbor<PointT>()}; using pcl::CorrespondenceEstimation<PointT, PointT>::source_; using pcl::CorrespondenceEstimation<PointT, PointT>::target_; };
使用时,将配准类(如ICP)的对应估计器替换为自定义子类即可:
pcl::IterativeClosestPoint<PointXYZ, PointXYZ> icp; auto corr_est = boost::make_shared<CorrespondenceEstimationOrganized<PointXYZ>>(); icp.setCorrespondenceEstimation(corr_est);
方案二:手动计算对应关系后传入配准类
如果不想自定义子类,更直接的方式是手动用OrganizedNeighbor计算所有源点到目标点的最近邻对应,再将结果传入配准类:
- 初始化
OrganizedNeighbor并设置目标点云 - 遍历源点云每个点,调用
nearestKSearch获取最近邻 - 生成
pcl::Correspondences对象存储有效对应(过滤距离过大的匹配) - 调用配准类的
setCorrespondences方法,跳过内部对应估计步骤
示例代码片段:
#include <pcl/search/organized.h> #include <pcl/registration/icp.h> // 源点云和目标点云 pcl::PointCloud<pcl::PointXYZ>::ConstPtr source, target; // 初始化OrganizedNeighbor pcl::OrganizedNeighbor<pcl::PointXYZ> organized_neighbor; organized_neighbor.setInputCloud(target); pcl::Correspondences correspondences; const double max_dist = 0.1; // 根据场景设置距离阈值 for (size_t i = 0; i < source->size(); ++i) { std::vector<int> indices(1); std::vector<float> distances(1); organized_neighbor.nearestKSearch((*source)[i], 1, indices, distances); if (distances[0] <= max_dist) { pcl::Correspondence corr; corr.index_query = static_cast<int>(i); corr.index_match = indices[0]; corr.distance = distances[0]; correspondences.push_back(corr); } } // 传入配准类 pcl::IterativeClosestPoint<pcl::PointXYZ, pcl::PointXYZ> icp; icp.setInputSource(source); icp.setInputTarget(target); icp.setCorrespondences(correspondences); // 执行配准 pcl::PointCloud<pcl::PointXYZ> aligned; icp.align(aligned);
这种方法无需修改PCL原有类,灵活性更高,适合快速验证需求。
内容的提问来源于stack exchange,提问作者oarfish
相关产品推荐
相关产品推荐

