点云配准,然后将配准后的点云保存为pcd文件

两个点云进行配准,然后将配准后的点云保存为pcd文件,本文是在《点云库PCL从入门到精通》基础上修改的。
pairwise_incremental_registration.cpp如下所示:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
//定义PCL点云的类型
typedef pcl::PointXYZ PointT;
typedef pcl::PointCloud<PointT> PointCloud;
typedef pcl::PointNormal PointNormalT;
typedef pcl::PointCloud<PointNormalT> PointCloudWithNormals;
void pairAlign (const PointCloud::Ptr cloud_src, const PointCloud::Ptr cloud_tgt,
                PointCloud::Ptr output, Eigen::Matrix4f &final_transform, bool downsample = false)
{
     
  PointCloud::Ptr src (new PointCloud);//存储滤波后源点云
  PointCloud::Ptr tgt (new PointCloud);//存储滤波后目标点云
  pcl::VoxelGrid<PointT> grid;       //处理滤波对象
  if (downsample)
  {
     
    std::cout<<"3 "<<std::endl;
    grid.setLeafSize (0.05, 0.05, 0.05); //设置滤波处理时采用的体素大小
    grid.setInputCloud (cloud_src);
    grid.filter (*src);
    grid.setInputCloud (cloud_tgt);
    grid.filter (*tgt);
  }
  else
  {
     
    src = cloud_src;
    tgt = cloud_tgt;
  }
  //输出其大小,并计算点云法线
  std::cout<<"src size "<<src->points.size()<<std::endl;
  std::cout<<"tgt size "<<tgt->points.size()<<std::endl;
  PointCloudWithNormals::Ptr points_with_normals_src (new PointCloudWithNormals);
  PointCloudWithNormals::Ptr points_with_normals_tgt (new PointCloudWithNormals);
  pcl::NormalEstimation<PointT, PointNormalT> norm_est;//点云法线估计对象
  pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ> ());
  norm_est.setSearchMethod (tree);//设置估计对象采用的搜索对象
  norm_est.setKSearch (30);//设置估计时进行搜索用的k数;
  norm_est.setInputCloud (src);
  norm_est.compute (*points_with_normals_src);
  //下面估计源点云和目标点云法线
  pcl::copyPointCloud (*src, *points_with_normals_src);
  norm_est.setInputCloud (tgt);
  norm_est.compute (*points_with_normals_tgt);
  pcl::copyPointCloud (*tgt, *points_with_normals_tgt);
  pcl::IterativeClosestPointNonLinear<PointNormalT, PointNormalT> reg;//配准对象
  reg.setTransformationEpsilon (1e-6);//设置收敛判断条件,越小精度越大,收敛也越慢;
  //将两个点云中对应点对之间的(src<->tgt)最大距离设置为10厘米,大于此值的不考虑
  reg.setMaxCorrespondenceDistance (0.1);  
  //设置源点云和目标点云
  reg.setInputSource (points_with_normals_src);
  reg.setInputTarget (points_with_normals_tgt);
  Eigen::Matrix4f Ti = Eigen::Matrix4f::Identity (), prev, targetToSource;
  PointCloudWithNormals::Ptr reg_result = points_with_normals_src;
  reg.setMaximumIterations (30);
    reg.align (*reg_result);
    std::cout<<"reg_result size "<<reg_result->points.size()<<std::endl;
    Ti = reg.getFinalTransformation () ;//* Ti;
  targetToSource = Ti.inverse();
  pcl::transformPointCloud (*cloud_tgt, *output, targetToSource);
  *output = *output + *cloud_src;
 }
int main (int argc, char** argv)
{
     
    PointCloud::Ptr result (new PointCloud), source (new PointCloud), target (new PointCloud);
    if(argc>3){
     
        std::cout<<"error argment "<<std::endl;
    } // 加载需要进行点云配准的源点云和目标点云。
      if (pcl::io::loadPCDFile<pcl::PointXYZ> ("capture0001.pcd", *source) == -1)
      {
     
        PCL_ERROR ("Couldn't read file test_pcd.pcd \n");
        return (-1);
      }
      if (pcl::io::loadPCDFile<pcl::PointXYZ> ("capture0002.pcd", *target) == -1)
      {
     
        PCL_ERROR ("Couldn't read file test_pcd.pcd \n");
        return (-1);
      }
           //ŽÓµãÔÆÖÐÒƳýNANµã
        std::vector<int> indices;
        pcl::removeNaNFromPointCloud(*source,*source, indices);
        pcl::removeNaNFromPointCloud(*target,*target, indices);
        Eigen::Matrix4f GlobalTransform = Eigen::Matrix4f::Identity (), pairTransform;
        PointCloud::Ptr temp (new PointCloud);
//    PCL_INFO ("Aligning %s (%d) with %s (%d).\n", data[i-1].), source->points.size (), data[i].f_name.c_str (), target->points.size ());
    std::cout<<"save cloud 1"<<std::endl;
    //调用子函数完成一组点云的配准,temp返回配准后两组点云在第//一组点云坐标系下的点云,pairTranse返回从目标点云到源点云的变//换矩阵。
    pairAlign (source, target, temp, pairTransform, false);
    std::cout<<"13 "<<std::endl;
    //把当前两两配对后的点云temp转换到全局坐标系下,返回result
    pcl::transformPointCloud (*temp, *result, GlobalTransform);
    //使用当前两组点云之间的变换更新全局变换
    GlobalTransform = pairTransform * GlobalTransform;
    std::cout<<"save cloud "<<std::endl;
    //逐个点打印,不建议使用
    /*for(size_t i=0;i<result->points.size();++i)
        std::cout<<"    "<<result->points[i].x<<" "<<result->points[i].y<<result->points[i].z<<std::endl;
    */pcl::io::savePCDFileASCII ("test_pcd.pcd", *result);
     std::cout<<"reg_result size "<<result->points.size()<<std::endl;//两个点云都转换到第一个点云坐标系下的总的点云的个数
    pcl::PCDWriter writer;
    writer.write<pcl::PointXYZ>("2.pcd", *result, false);//保存转换到第一个点云坐标系下当前配准后的两组点云result到文件2.pcd中
}

CMakeLists.txt文件如下所示:

cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
project(tuto-pairwise)
find_package(PCL 1.4 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})		
add_definitions(${PCL_DEFINITIONS})
add_definitions(-Wno-deprecated -DEIGEN_DONT_VECTORIZE -DEIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT)
add_executable (pairwise_incremental_registration pairwise_incremental_registration.cpp)
target_link_libraries (pairwise_incremental_registration ${PCL_LIBRARIES})

系统Ubuntu16.04,基于ROS kinetic平台下,编译过程

mkdir build
cd build
cmake ..
make
./pairwise_incremental_registration

pcd测试文件如有需要,可在下面留下邮箱,我会发
如有什么问题,还请各位多多指教

你可能感兴趣的:(PCL,c++)