如何仅通过平移使用PCL实现两点云配准?
解决PCL ICP配准中禁用旋转的问题
PCL的标准ICP类没有直接提供禁用旋转的开关,但可以通过以下两种方式实现仅平移的点云配准:
方法一:自定义仅平移的ICP子类
继承pcl::IterativeClosestPoint并重写computeTransformation方法,强制在配准过程中只计算平移向量,旋转部分固定为单位矩阵。示例代码如下:
template <typename PointT> class ICPTranslationOnly : public pcl::IterativeClosestPoint<PointT, PointT> { protected: void computeTransformation(pcl::PointCloud<PointT>& output, const Eigen::Matrix4f& guess) override { // 初始化变换矩阵,旋转部分设为单位矩阵 this->final_transformation_ = guess; this->final_transformation_.block<3, 3>(0, 0) = Eigen::Matrix3f::Identity(); for (int iter = 0; iter < this->max_iterations_; ++iter) { std::vector<int> indices_source, indices_target; this->correspondence_rejector_->getCorrespondences(indices_source, indices_target); if (indices_source.empty()) break; // 计算源点云和目标点云对应点的质心,仅求解平移 Eigen::Vector4f centroid_source, centroid_target; pcl::compute3DCentroid(*this->input_, indices_source, centroid_source); pcl::compute3DCentroid(*this->target_, indices_target, centroid_target); Eigen::Matrix4f transformation; transformation.setIdentity(); transformation.block<3, 1>(0, 3) = centroid_target.head<3>() - centroid_source.head<3>(); // 应用当前平移变换 pcl::transformPointCloud(*this->input_, output, transformation); this->final_transformation_ = transformation * this->final_transformation_; // 检查收敛条件 float fitness = this->computeFitnessScore(output, *this->target_, this->max_correspondence_distance_); if (fitness < this->euclidean_fitness_epsilon_) break; } } };
使用时直接替换原ICP类即可:
ICPTranslationOnly<PointT> icp; // 原有的参数设置保持不变 icp.setMaximumIterations(max_iterations); icp.setMaxCorrespondenceDistance(max_correspondence_distance); // ...其他参数 icp.setInputSource(source); icp.setInputTarget(target); icp.align(*result);
方法二:事后修正变换矩阵
如果不需要在配准过程中约束旋转,可以在ICP计算完成后,手动将变换矩阵的旋转部分替换为单位矩阵,仅保留平移分量:
icp.align(*result); Eigen::Matrix4f transform = icp.getFinalTransformation(); // 重置旋转部分为单位矩阵 transform.block<3, 3>(0, 0) = Eigen::Matrix3f::Identity(); // 应用修正后的变换到源点云 pcl::transformPointCloud(*source, *result, transform);
这种方法简单直接,但缺点是ICP仍会先计算包含旋转的变换,再被强制修正,可能在某些场景下效率较低。
内容的提问来源于stack exchange,提问作者Marco F.
相关产品推荐
相关产品推荐

