You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何仅通过平移使用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.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 03:57:52