当前位置: 首页 > article >正文

PCL库简单NDT算法配准

#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/registration/ndt.h>

int main(int argc, char** argv)
{
    // 检查输入参数
    if (argc != 3)
    {
        PCL_ERROR("请提供两个PCD文件作为输入: source.pcd target.pcd\n");
        return (-1);
    }

    // 读取源点云和目标点云
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_source(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_target(new pcl::PointCloud<pcl::PointXYZ>);

    if (pcl::io::loadPCDFile<pcl::PointXYZ>(argv[1], *cloud_source) == -1)
    {
        PCL_ERROR("无法读取文件 %s\n", argv[1]);
        return (-1);
    }
    if (pcl::io::loadPCDFile<pcl::PointXYZ>(argv[2], *cloud_target) == -1)
    {
        PCL_ERROR("无法读取文件 %s\n", argv[2]);
        return (-1);
    }

    // 创建NDT配准对象
    pcl::NormalDistributionsTransform<pcl::PointXYZ, pcl::PointXYZ> ndt;

    // 设置NDT参数
    ndt.setTransformationEpsilon(0.1);
    ndt.setStepSize(0.9);
    ndt.setResolution(0.9);
    ndt.setMaximumIterations(10);

    // 设置源点云和目标点云
    ndt.setInputSource(cloud_source);
    ndt.setInputTarget(cloud_target);

    // 进行配准
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_registered(new pcl::PointCloud<pcl::PointXYZ>);
    ndt.align(*cloud_registered);

    if (ndt.hasConverged())
    {
        std::cout << "配准成功!" << std::endl;
        std::cout << "迭代次数: " << ndt.getFinalNumIteration() << std::endl;
        std::cout << "最终变换矩阵: \n" << ndt.getFinalTransformation() << std::endl;
    }
    else
    {
        std::cout << "配准失败!" << std::endl;
    }
    pcl::io::savePCDFile("cloud_registered.pcd",*cloud_registered);

    return 0;
}

简单调了一下参数,效果比icp好一些,当然了可能是icp没有调参的原因。。

  1. setTransformationEpsilon(1.0):

    • setTransformationEpsilon 设置了变换矩阵更新的epsilon值,这是一个收敛条件,用于确定何时停止迭代。
    • 当连续两次迭代的变换矩阵变化的Frobenius范数小于这个epsilon值时,算法认为已经收敛,迭代过程会停止。
    • 值越小,要求的精度越高,可能需要更多的迭代次数。
  2. setStepSize(1.0):

    • setStepSize 定义了在每一步迭代中,变换矩阵可以更新的最大尺度。
    • 这个参数控制了搜索空间的步长,值越大,每次迭代的搜索范围越大,可能会跳过最优解,值越小,搜索越精细,但迭代次数可能会增加。
  3. setResolution(1.0):

    • setResolution 设置了NDT算法中使用的网格的分辨率。
    • 分辨率越高,网格单元越小,搜索空间被划分得越精细,配准结果通常更准确,但计算量也越大。
    • 值越小,网格单元越小,搜索越精细,但计算量也越大。
  4. setMaximumIterations(1000):

    • setMaximumIterations 设置了算法的最大迭代次数。
    • 即使算法没有收敛,达到这个迭代次数后,算法也会停止迭代。
    • 这个参数确保了算法不会无限运行下去。

http://www.kler.cn/news/327488.html

相关文章:

  • mini-lsm通关笔记Week2Overview
  • SpringBoot中使用XXL-JOB实现灵活控制的分片处理方案
  • C++的类型转换
  • Redis: 主从复制读写分离环境搭建
  • 2024电脑视频剪辑软件全解析与推荐
  • Prompt:在AI时代,提问比答案更有价值
  • O2OA(翱途)服务器故障排查
  • 学习经验分享【38】YOLOv11解读——最新YOLO版本
  • linux文件编程_文件
  • 记录一次gRpc流式操作
  • 正则表达式的使用示例--Everything文件检索批量重命名工具
  • 使用 Python 实现图形学的辐射度算法
  • Flask-2
  • Gpt4.0最新保姆级教程开通升级
  • 如何使用 Python 读取数据量庞大的 excel 文件
  • PostgreSQL+MybatisPlus,设置逻辑删除字段后查询出现:操作符不存在: boolean = integer 错误
  • 【mmengine】配置器(config)(进阶)继承与导出,命令行修改配置
  • 鸿蒙开发(NEXT/API 12)【硬件(常见问题)】驱动开发服务
  • 3-3 AUTOSAR RTE 对SR Port的作用
  • 51单片机的智能停车场【proteus仿真+程序+报告+原理图+演示视频】
  • Ubuntu 手动安装 ollama
  • 音视频入门基础:FLV专题(9)——Script Tag简介
  • mysql迁移postgreSql windows 工具
  • SQL SERVER 从嫌弃存储到爱上存储过程我给存储过程开发了版本控制工具和远程调试功能...
  • 基于ESP8266使用OLED显示温湿度和时间
  • Jmeter常用函数、逻辑控制器
  • 025.Oracle_DBMS_job定时任务
  • 单片机在控制和自动化任务中的应用场景广泛
  • 关于区块链的安全和隐私
  • 国外问卷调查匠哥已经不带人了,但是还可以交流