0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

点云滤波与匹配进阶干货收藏

新机器视觉 来源:新机器视觉 2023-11-06 11:03 次阅读

0. 简介

之前作者专门为点云匹配写了几篇博客,但是我们发现最近几年有更多的新方法已经在不断地被使用。

同时之前有些内容也没有很好的概括,所以这里我们将作为一篇进阶文章来介绍这些方法的使用。

1. 地面点去除

处了使用一些复杂的方法(FEC)或是一些简单的方法(根据高度来滤除)以外,还可以使用Ransac的方法完成平面拟合

#include 
#include 
#include 
#include 
#include 


void RemovePointsUnderGround(const pcl::PointCloud& cloud_in,
               pcl::PointCloud& cloud_out)
{
  // 对输入点云进行降采样
  pcl::PointCloud::Ptr cloud_downsampled(new pcl::PointCloud);
  pcl::VoxelGrid voxel_grid;
  voxel_grid.setInputCloud(cloud_in.makeShared());
  voxel_grid.setLeafSize(0.1f, 0.1f, 0.1f); // 设置体素格大小
  voxel_grid.filter(*cloud_downsampled);


  // 创建一个滤波器对象,用于提取地面平面
  pcl::PointCloud::Ptr cloud_filtered(new pcl::PointCloud);
  pcl::PassThrough pass_through;
  pass_through.setInputCloud(cloud_downsampled);
  pass_through.setFilterFieldName("z"); // 对z轴进行滤波
  pass_through.setFilterLimits(-1.5, 0.5); // 设置滤波范围,过滤掉z轴在-1.5到0.5之间的点
  pass_through.filter(*cloud_filtered);


  // 创建一个分割对象,用于提取地面平面
  pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
  pcl::PointIndices::Ptr inliers(new pcl::PointIndices);
  pcl::SACSegmentation segmentation;
  segmentation.setInputCloud(cloud_filtered);
  segmentation.setModelType(pcl::SACMODEL_PLANE);
  segmentation.setMethodType(pcl::SAC_RANSAC);
  segmentation.setDistanceThreshold(0.1); // 设置距离阈值,点到平面的距离小于该阈值的点将被认为是地面点
  segmentation.segment(*inliers, *coefficients);


  // 创建一个提取对象,用于提取地面点
  pcl::PointCloud::Ptr cloud_ground(new pcl::PointCloud);
  pcl::ExtractIndices extract;
  extract.setInputCloud(cloud_filtered);
  extract.setIndices(inliers);
  extract.setNegative(false); // 提取地面点,即保留inliers对应的点
  extract.filter(*cloud_ground);


  // 创建一个提取对象,用于提取非地面点
  pcl::PointCloud::Ptr cloud_non_ground(new pcl::PointCloud);
  extract.setNegative(true); // 提取非地面点,即去除inliers对应的点
  extract.filter(*cloud_non_ground);


  // 将结果保存到输出点云中
  cloud_out = *cloud_non_ground;
}

2. PCA主成分判别

除了去除点云以外,还可以通过主成分判别来判断我们分割的是否是地面。其中eigenvectors()函数得到的矩阵中的三个列向量分别对应于数据的主成分轴。

这些主成分轴是按照数据方差的降序排列的,即第一个列向量对应的是数据的第一主成分轴,第二个列向量对应的是数据的第二主成分轴,第三个列向量对应的是数据的第三主成分轴。对于PCA的特征值和特征向量可以从这里理解:

https://blog.csdn.net/lazysnake666/article/details/122404671

#include 
#include 
#include 
#include 


bool EstimatePlane(const pcl::PointCloud& cloud)
{


  // 将输入点云数据转换为PCL点云格式
  for (const auto& point : cloud)
  {
    pcl::PointXYZ pclPoint;
    pclPoint.x = point.x();
    pclPoint.y = point.y();
    pclPoint.z = point.z();
    cloud->push_back(pclPoint);
  }


  // 创建PCA对象
  pcl::PCA pca;
  pca.setInputCloud(cloud);


  // 计算主成分
  Eigen::Vector3f eigenValues = pca.getEigenValues();
  Eigen::Matrix3f eigenVectors = pca.getEigenVectors();


  // 获取地面法向量,因为最小的就是第三列,所以最后一列是地面(0,0,1),如果是墙面那就(x,1-x,0)
  Eigen::Vector3f groundNormal = eigenVectors.col(2);#eigen_vector.block<3, 1>(0, 2)//最小成分的主成分向量,对应的是地面的法线,因为地面XY都存在比较大的主成分
  // 如果是其他的比如灯杆这种,一般的就会是fabs(eigen_vector.block<3, 1>(0, 0).dot(Eigen::UnitZ()))的形式,也就是最大主成分,沿着最大主成分方向


  bool is_ground = (fabs(groundNormal.dot(
               Eigen::UnitZ())) > 0.98) &&
             (eigenValues(2) < 0.05 * 0.05);//最小得列和地面法线重合|a||b|cos,并且eigenValues重要程度满足要求,因为地面基本等于0,所以特征值也很小   https://blog.csdn.net/xinxiangwangzhi_/article/details/118228160
    // 如果是其他的比如灯杆这种,一般的就会是eigen_values(0) > 10 * eigen_values(1)


  return is_ground;
}

3. GICP配准

GICP配准这块在之前的博客经典论文阅读之-GICP(ICP大一统)中已经详细讲过了,下面就是一个示例代码

Eigen::Matrix4d gicp_trans(
  pcl::PointCloud::Ptr source_cloud,
  pcl::PointCloud::Ptr target_cloud) {
 CHECK(source_cloud);
 CHECK(target_cloud);


 pcl::GeneralizedIterativeClosestPoint gicp;
 gicp.setInputSource(source_cloud);
 gicp.setInputTarget(target_cloud);




 gicp.setMaxCorrespondenceDistance(10.0);
 gicp.setMaximumIterations(100);
 gicp.setMaximumOptimizerIterations(100);
 gicp.setRANSACIterations(100);
 gicp.setRANSACOutlierRejectionThreshold(1.0);
 gicp.setTransformationEpsilon(0.01);
 gicp.setUseReciprocalCorespondences(false);


 LOG(INFO) << "MaxCorrespondenceDistance: " << gicp.getMaxCorrespondenceDistance();
  LOG(INFO) << "MaximumIterations: " << gicp.getMaximumIterations();
  LOG(INFO) << "MaximumOptimizerIterations: " << gicp.getMaximumOptimizerIterations();
  LOG(INFO) << "RANSACIterations: " << gicp.getRANSACIterations();
  LOG(INFO) << "RANSACOutlierRejectionThreshold: " << gicp.getRANSACOutlierRejectionThreshold();
  LOG(INFO) << "TransformationEpsilon: " << gicp.getTransformationEpsilon();
  LOG(INFO) << "MaxCorrespondenceDistance: " << gicp.getMaxCorrespondenceDistance();
  LOG(INFO) << "RANSACOutlierRejectionThreshold: " << gicp.getRANSACOutlierRejectionThreshold();
  LOG(INFO) << "UseReciprocalCorrespondences: " << gicp.getUseReciprocalCorrespondences();


  pcl::PointCloud::Ptr aligned_source =
   boost::make_shared>();
 gicp.align(*aligned_source);
 CHECK(aligned_source);
 LOG(INFO) << "Final transformation: " << std::endl << gicp.getFinalTransformation();
  if (gicp.hasConverged()) {
    LOG(INFO) << "GICP converged." << std::endl
              << "The score is " << gicp.getFitnessScore();
  } else {
    LOG(INFO) << "GICP did not converge.";
  }


  LOG(INFO) << "Saving aligned source cloud to: " << params_.aligned_cloud_filename;
  pcl::savePCDFile(params_.aligned_cloud_filename, *aligned_source);


  return  gicp.getFinalTransformation();
}

4. ikd-Tree配准

ikd-Tree的建图配准离不开eskf的相关内容,相关的代码太多了;所以这里大概整理了一下思路, 即导入地图,然后将当前的点云与GPS结合转到全局坐标系下,然后使用ikdtree完成检索,并传入ESKF中完成优化计算(如果点比较少还可以放弃ESKF,转而用EstimatePlane来估算出平面,并利用点到平面的距离残差来估算)

int feats_down_size = 0


esekfom::esekf kf;
state_ikfom state_point;
state_point = kf.get_x();
state_point.pos = Eigen::Vector3d(init_pos[0], init_pos[1], init_pos[2]);
Eigen::Quaterniond q(init_rot[3], init_rot[0], init_rot[1], init_rot[2]);
Sophus::SO3 SO3_q(q);
state_point.rot = SO3_q;
kf.change_x(state_point);
// IMU预积分部分(也可以用GPS代替IMU做积分)


//根据最新估计位姿 增量添加点云到map
void init_ikdtree(KD_TREE ikdtree)
{
  //加载读取点云数据到cloud中
  string all_points_dir(string(string(ROOT_DIR) + "PCD/") + "GlobalMap_ikdtree.pcd");
  if (pcl::loadPCDFile(all_points_dir, *cloud) == -1)
  {
    PCL_ERROR("Read file fail!
");
  }


  ikdtree.set_downsample_param(filter_size_map_min);
  ikdtree.Build(cloud->points);
  std::cout << "---- ikdtree size: " << ikdtree.size() << std::endl;
}


void IkdTreeMapping(pcl::PointCloud::Ptr feats_undistort)//这个拿到的是转到全局坐标系下去过噪声的点
{
 KD_TREE ikdtree;
 if (ikdtree_.Root_Node == nullptr) {
  KD_TREE ikdtree;
 }
 pcl::VoxelGrid downSizeFilterSurf;
 downSizeFilterSurf.setLeafSize(0.5, 0.5, 0.5);
 //点云下采样
 downSizeFilterSurf.setInputCloud(feats_undistort);
 PointCloudXYZI::Ptr feats_down_body(new PointCloudXYZI()); //畸变纠正后降采样的单帧点云,lidar系
 downSizeFilterSurf.filter(*feats_down_body);
 feats_down_size = feats_down_body->points.size();


 // std::cout << "feats_down_size :" << feats_down_size << std::endl;
  if (feats_down_size < 5)
  {
      ROS_WARN("No point, skip this scan!
");
      return;
  }


  /*** iterated state estimation ***/
  Nearest_Points.resize(feats_down_size); //存储近邻点的vector
  kf.update_iterated_dyn_share_modified(0.001, feats_down_body, ikdtree, Nearest_Points, 4, true);#匹配相关的内容都在里面,核心就是ikdtree.Nearest_Search


  state_point = kf.get_x();
  pos_lid = state_point.pos + state_point.rot.matrix() * state_point.offset_T_L_I;
bainji :hf 

编辑:黄飞

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • gps
    gps
    +关注

    关注

    22

    文章

    2895

    浏览量

    166195
  • PCA
    PCA
    +关注

    关注

    0

    文章

    89

    浏览量

    29595

原文标题:点云滤波与匹配进阶

文章出处:【微信号:vision263com,微信公众号:新机器视觉】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    立体视觉中误匹配滤波方法的研究

    从二维空间和三维空间2种角度研究误匹配滤波算法,提出在匹配前用于降低误匹配的灰度预处理算法和一种基于真实控制的视差
    发表于 04-13 09:58 17次下载

    改进的特征匹配算法

    特征匹配是计算机视觉中的关键步骤,在很多领域中都有着的重要应用。通过对当前图像特征匹配方法的研究,提取一种基于特征的灰度量和几何特征量
    发表于 05-19 17:20 0次下载
    改进的特征<b class='flag-5'>点</b><b class='flag-5'>匹配</b>算法

    双边滤波去噪算法

    针对三维数据模型在去噪光顺中存在不同尺度噪声的问题,提出一种基于噪声分类的双边滤波去噪算法。该算法首先将噪声细分为大尺度和小尺度噪声
    发表于 01-05 10:51 2次下载
    双边<b class='flag-5'>滤波</b><b class='flag-5'>点</b><b class='flag-5'>云</b>去噪算法

    SAW滤波匹配的目的和方法

    如何在电路板上安装和匹配 SAW 滤波器,发挥SAW 滤波器的最佳性能,这对于应用SAW 滤波器的人员很重要,否则再好的产品也达不到使用者的要求。所以一般的 SAW
    的头像 发表于 05-04 17:53 7180次阅读
    SAW<b class='flag-5'>滤波</b>器<b class='flag-5'>匹配</b>的目的和方法

    无序抓取の3D匹配案例分享

    这是一个实际拍摄的云图,经过了坐标系纠正变换,更方便查看点位置。里面有一块平面就是我们需要匹配的目标点
    的头像 发表于 09-24 11:39 3496次阅读

    匹配与ICP算法基本思想

    ICP(Iterative Closest Point迭代最近)算法是一种集对集配准方法。如下图所示,PR(红色)和RB(蓝色
    的头像 发表于 09-24 12:43 3859次阅读
    <b class='flag-5'>点</b><b class='flag-5'>云</b><b class='flag-5'>匹配</b>与ICP算法基本思想

    LabVIEW:适合平滑的双边滤波

    摘要: 我们通过扫描仪获得物体的,经常掺杂着噪音。产生噪音的原因可能有很多多种,例如,切向的采集方向、环境光干扰、物体材质的反射等因素导致。因此设置一种滤波方法,可以去除噪音有保留物体原有物体
    的头像 发表于 11-05 18:16 3480次阅读
    LabVIEW:适合<b class='flag-5'>点</b><b class='flag-5'>云</b>平滑的双边<b class='flag-5'>滤波</b>器

    【CC2530授课笔记】课程列表汇总 【超级干货】【建议收藏

    【CC2530授课笔记】课程列表汇总 【超级干货】【建议收藏
    发表于 11-29 19:36 0次下载
    【CC2530授课笔记】课程列表汇总 【超级<b class='flag-5'>干货</b>】【建议<b class='flag-5'>收藏</b>】

    SAW滤波器的使用和匹配

    如何在电路板上安装和匹配 SAW 滤波器,发挥 SAW 滤波器的最佳性能,这对于应用 SAW 滤波器的人员很重要,为此我们介绍 SAW 滤波
    的头像 发表于 10-08 16:03 3249次阅读

    「实用干货」7条实用的PCB布线规则,可收藏

    「实用干货」7条实用的PCB布线规则,可收藏
    的头像 发表于 02-01 08:36 1241次阅读

    干货 | 超实用总结,一文通吃所有整流滤波电路

    干货 | 超实用总结,一文通吃所有整流滤波电路
    的头像 发表于 03-23 21:19 1241次阅读
    <b class='flag-5'>干货</b> | 超实用总结,一文通吃所有整流<b class='flag-5'>滤波</b>电路

    SDMNet:大规模激光雷达配准的稀疏到稠密匹配网络

    为了处理上述的问题,我们提出了SDMNet,一种新的由稀疏到密集的针对大规模室外的配准方法。稀疏到稠密匹配方案如图1(c)所示。具体而言,我们将配准问题分为两个阶段,即稀疏匹配阶段
    的头像 发表于 05-24 15:53 1201次阅读
    SDMNet:大规模激光雷达<b class='flag-5'>点</b><b class='flag-5'>云</b>配准的稀疏到稠密<b class='flag-5'>匹配</b>网络

    干货】推荐收藏!电力电子FPGA实时仿真技术浅析

    新秀!PPEC——你无法想象做电源竟如此简单!●FPGA实时仿真天花板——NetBox电力电子仿真器●PPEC教你做电源——移相全桥电路原文标题:【干货】推荐收藏
    的头像 发表于 06-14 11:42 960次阅读
    【<b class='flag-5'>干货</b>】推荐<b class='flag-5'>收藏</b>!电力电子FPGA实时仿真技术浅析

    PCL匹配器滤除方法

    匹配器 2.1 ICP精配准 template typename PointCloudPtr > bool ex_segmentor::icp_registration
    的头像 发表于 11-28 11:30 464次阅读

    什么是匹配滤波器?如何理解匹配滤波器?

    [导读]为增进大家对匹配滤波器的认识,本文将对匹配滤波器、匹配滤波器的详细理解予以介绍。 匹配滤‍波器作为滤波器的一种,在信号处理系统中发挥
    的头像 发表于 01-12 08:39 1662次阅读