pcl学习笔记:pcl官方教程学习(代码片段)

Sakurazzy Sakurazzy     2023-02-06     680

关键词:

PCL学习笔记(二):PCL官方教程学习

本节学习PCL的官方文档教程,记录学习过程


PCD文件制作

在gazebo中建立仿真环境,通过Realsense获取点云,保存为PCD文件,一个是走廊path_corner.pcd,一个是几何物体objects.pcd


Features

表面法线提取

参考官方文档:Estimating Surface Normals in a PointCloud

#include <ros/ros.h>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/features/normal_3d.h>
#include <pcl_conversions/pcl_conversions.h>
#include <sensor_msgs/PointCloud2.h>

// 计算表面法线
pcl::PointCloud<pcl::Normal>::Ptr estimate_surface_normals( pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
    // Create the normal estimation class, and pass the input dataset to it
    pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
    ne.setInputCloud (cloud);
    // Create an empty kdtree representation, and pass it to the normal estimation object.
    // Its content will be filled inside the object, based on the given input dataset (as no other search surface is given).
    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ> ());
    ne.setSearchMethod (tree);
    // Output datasets
    pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);
    // Use all neighbors in a sphere of radius 3cm
    ne.setRadiusSearch (0.03);
    // Compute the features
    ne.compute (*cloud_normals);
    
    return cloud_normals;

 
int main(int argc, char** argv) 
    // 读取pcd点云文件
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
    if (pcl::io::loadPCDFile<pcl::PointXYZ>("./data/objects.pcd", *cloud) == -1) 
        PCL_ERROR("Couldn't read file objects.pcd\\n");
        return(-1);
    
    // 计算法线
     pcl::PointCloud<pcl::Normal>::Ptr normals (new pcl::PointCloud<pcl::Normal>);
    normals = estimate_surface_normals(cloud);
    std::cout<<"normals points size:"<<normals->points.size()<<std::endl;
    return 0;

其他参考博客:
pcl::Normal的定义以及cout
调用pcl计算法向量,并将法向量可视化
PCL:从法线计算到曲率计算并可视化


Keypoints

提取NARF关键点

参考代码:PCL系列——从深度图像(RangeImage)中提取NARF关键点
参考博客:
PCL关键点检测–NARF关键点
点云库PCL学习——NARF关键点

NARF(Normal Aligned Radial Feature)关键点是为了从深度图像中识别物体而提出的,关键点探测的重要一步是减少特征提取时的搜索空间,把重点放在重要的结构上。
对NARF关键点提取过程有以下要求:提取的过程必须将边缘以及物体表面变化信息考虑在内;关键点的位置必须稳定,可以被重复探测,即使换了不同视角;关键点所在的位置必须具有稳定的支持区域,可以计算描述子并进行唯一的法向量估计。
该方法提取步骤如下:
1、遍历每个深度图像点,通过寻找在邻近区域有深度突变的位置进行边缘检测。
2、遍历每个深度图像点,根据邻近区域的表面变化决定一种测度表面变化的系数,以及变化的主方向。
3、根据第二步找到的主方向计算兴趣值,表征该方向与其它方向的不同,以及该处表面的变化情况,即该点有多稳定
4、对兴趣值进行平滑滤波
5、进行无最大值压缩找到最终的关键点,即为NARF关键点

关键代码

  //从点云数据,创建深度图像
  float noise_level = 0.0;
  float min_range = 0.0f;
  int border_size = 1;
  boost::shared_ptr<pcl::RangeImage> range_image_ptr (new pcl::RangeImage); //创建RangeImage对象(指针)
  pcl::RangeImage& range_image = *range_image_ptr;  //引用
  range_image.createFromPointCloud (point_cloud, angular_resolution, pcl::deg2rad (360.0f), pcl::deg2rad (180.0f),
                                   scene_sensor_pose, coordinate_frame, noise_level, min_range, border_size); //从点云创建深度图像
  range_image.integrateFarRanges (far_ranges); //整合远距离点云
  if (setUnseenToMaxRange)
    range_image.setUnseenToMaxRange ();
    
  //提取NARF关键点
  pcl::RangeImageBorderExtractor range_image_border_extractor; //创建深度图像的边界提取器,用于提取NARF关键点
  pcl::NarfKeypoint narf_keypoint_detector (&range_image_border_extractor); //创建NARF对象
  narf_keypoint_detector.setRangeImage (&range_image);
  narf_keypoint_detector.getParameters ().support_size = support_size;
  //narf_keypoint_detector.getParameters ().add_points_on_straight_edges = true;
  //narf_keypoint_detector.getParameters ().distance_for_additional_points = 0.5;

运行结果如下,提取了10个特征点


KdTree

A k-d tree, or k-dimensional tree, is a data structure used in computer science for organizing some number of points in a space with k dimensions. It is a binary search tree with other constraints imposed on it. K-d trees are very useful for range and nearest neighbor searches.

KdTree常用于进行范围搜索或K近邻搜索的计算
参考代码:How to use a KdTree to search

#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <vector>
#include <iostream>
 
int main(int argc, char** argv) 
    // 读取pcd点云文件
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
    if (pcl::io::loadPCDFile<pcl::PointXYZ>("./data/objects.pcd", *cloud) == -1) 
        PCL_ERROR("Couldn't read file objects.pcd\\n");
        return(-1);
    

    // 构造kd tree
    pcl::KdTreeFLANN<pcl::PointXYZ> kdtree;
    kdtree.setInputCloud (cloud);
    
    // 选取搜索点
    pcl::PointXYZ searchPoint;
    searchPoint.x = 0.1;
    searchPoint.y = 0.1;
    searchPoint.z = 0.1;

    // K nearest neighbor search
    int K = 10;
    std::vector<int> pointIdxKNNSearch(K);
    std::vector<float> pointKNNSquaredDistance(K);

    std::cout << "K nearest neighbor search at (" << searchPoint.x << " " << searchPoint.y  << " " << searchPoint.z<< ") with K=" << K << std::endl;

    if ( kdtree.nearestKSearch (searchPoint, K, pointIdxKNNSearch, pointKNNSquaredDistance) > 0 )
    
    for (std::size_t i = 0; i < pointIdxKNNSearch.size (); ++i)
        std::cout << "    "  <<   (*cloud)[ pointIdxKNNSearch[i] ].x 
                << " " << (*cloud)[ pointIdxKNNSearch[i] ].y 
                << " " << (*cloud)[ pointIdxKNNSearch[i] ].z 
                << " (squared distance: " << pointKNNSquaredDistance[i] << ")" << std::endl;
    

    // Neighbors within radius search
    std::vector<int> pointIdxRadiusSearch;
    std::vector<float> pointRadiusSquaredDistance;
    float radius = 1;

    std::cout << "Neighbors within radius search at (" << searchPoint.x  << " " << searchPoint.y  << " " << searchPoint.z<< ") with radius=" << radius << std::endl;

    if ( kdtree.radiusSearch (searchPoint, radius, pointIdxRadiusSearch, pointRadiusSquaredDistance) > 0 )
    
    for (std::size_t i = 0; i < pointIdxRadiusSearch.size (); ++i)
        std::cout << "    "  <<   (*cloud)[ pointIdxRadiusSearch[i] ].x 
                << " " << (*cloud)[ pointIdxRadiusSearch[i] ].y 
                << " " << (*cloud)[ pointIdxRadiusSearch[i] ].z 
                << " (squared distance: " << pointRadiusSquaredDistance[i] << ")" << std::endl;
    
   
    return 0;


Range Image

How to create a range image from a point cloud

参考代码:How to create a range image from a point cloud

根据输入的PCD文件生成Range Image,并进行可视化,结果如下图所示

How to extract borders from range images

参考代码:
How to extract borders from range images
【点云处理技术之PCL】range image——提取深度图像的边界并可视化
从深度图像中提取三种边界:
object borders:目标最外层的边界
veil points:障碍物边界和阴影边界之间的插值点
shadow border:与遮挡相邻的背景点

关键代码

  pcl::RangeImageBorderExtractor border_extractor(&range_image);
  pcl::PointCloud<pcl::BorderDescription> border_descriptions;
  border_extractor.compute(border_descriptions);

运行结果


Segmentation

Plane model segmentation

参考代码:Plane model segmentation
参考博客:PCL系列——平面模型分割

完成平面模型的分割

Cylinder model segmentation

参考代码:Cylinder model segmentation
参考博客:
PCL 平面、圆柱 模型分割
利用 PCL 分割平面上的物体

算法流程:

  1. 直通滤波在Z轴上滤除桌后的点云,得到滤波后的点云cloud_filtered
  2. 法线估计,输入为cloud_filtered,得到法线估计结果cloud_normals
  3. 平面分割,使用RANSAC算法进行平面分割,输入为cloud_filtered和cloud_normals,需要设置最大迭代次数、距离阈值等参数,得到平面分割的4个系数coefficients_plane,然后通过extract对输入点云cloud_filtered进行提取
  4. 反向提取剩余的点云,得到cloud_filtered2,获取法线cloud_normals2
  5. 圆柱分割,同样使用RANSAC算法,输入为cloud_filtered2和cloud_normals2,设置相应的参数,得到分割系数coefficients_cylinder,通过extract提取圆柱点云

原PCD文件

分割结果

pcl学习笔记:环境安装(代码片段)

PCL学习笔记(一):环境安装Realsense安装ROS中PCL的简单使用修改点云RGB颜色PCL滤波参考博客学习ROS中的PCL使用,完成Realsense安装,PCL的简单使用Realsense安装官方源码:https://github.com/IntelRealSense/realsense-ros参... 查看详情

pcl学习笔记:平面和直线提取(代码片段)

PCL学习笔记(三):平面和直线提取仿真环境地面提取关键代码提取结果直线提取关键代码提取结果本节基于学习笔记(二)所学习的处理方法,在Gazebo中搭建仿真环境,提取地面和墙壁仿真环境在Gaze... 查看详情

pcl学习笔记:平面和直线提取(代码片段)

PCL学习笔记(三):平面和直线提取仿真环境地面提取关键代码提取结果直线提取关键代码提取结果本节基于学习笔记(二)所学习的处理方法,在Gazebo中搭建仿真环境,提取地面和墙壁仿真环境在Gaze... 查看详情

pcl学习笔记:环境安装(代码片段)

PCL学习笔记(一):环境安装Realsense安装ROS中PCL的简单使用修改点云RGB颜色PCL滤波参考博客学习ROS中的PCL使用,完成Realsense安装,PCL的简单使用Realsense安装官方源码:https://github.com/IntelRealSense/realsense-ros参... 查看详情

pcl学习笔记:环境安装(代码片段)

PCL学习笔记(一):环境安装Realsense安装ROS中PCL的简单使用修改点云RGB颜色PCL滤波参考博客学习ROS中的PCL使用,完成Realsense安装,PCL的简单使用Realsense安装官方源码:https://github.com/IntelRealSense/realsense-ros参... 查看详情

pcl点云库安装及学习(2021.7.28)(代码片段)

PCL点云库学习2021.7.281、PCL简介2、Win10系统下PCL环境配置2.1前提环境(Win1064位+VisualStudio2015)2.2方式一:源码编译(过程繁琐但通用性强)2.3方式二:安装包安装(简单易懂,推荐使用)3、PCL项目... 查看详情

激光slam学习笔记3--轨迹建图经验接口介绍(代码片段)

背景:如果给了一条轨迹和轨迹时间戳上的激光点云,那么拼接地图是一个有趣的事情。概要:先介绍来自liosam里面手动计算的接口,后面介绍一种pcl自带的接口。1、手动计算的接口该接口采用手撕方式写的࿰... 查看详情

qt+pcl点云学习(代码片段)

PCL点云学习概念PointCloudLibraries点云库和opencv处理图像一样,不过是3D图像的处理支持文件格式pcd格式文件PCD不是第一个支持3D点云数据的文件类型,尤其是计算机图形学和计算几何学领域,已经创建了很多格式来描述... 查看详情

qt+pcl点云学习(代码片段)

PCL点云学习概念PointCloudLibraries点云库和opencv处理图像一样,不过是3D图像的处理支持文件格式pcd格式文件PCD不是第一个支持3D点云数据的文件类型,尤其是计算机图形学和计算几何学领域,已经创建了很多格式来描述... 查看详情

unity官方教程学习简单笔记(代码片段)

Unity官方出了一个RPG的教程,学习了第一部分,感觉收获还是蛮大的。2020版商城导入位置变了,下载很慢。渲染管线在游戏中影响太大了,颜值就是正义,要赶快学习。程序结构Unity项目里面怎么组织,这... 查看详情

学习pcl库你应该知道的c++特性

要学会PCL首先要对C++进行学习,所以这里我们首先对PCL库的代码中常见的C++的技巧进行整理和概述,并且对其中的难点进行细化讲解。首先我们搞清楚PCL库的文件形式、是一个以CMake构建的项目,库中主要... 查看详情

echarts学习笔记(代码片段)

...求用echarts,由于之前没有接触过,临时边学便用。开始学习echarts首先想到的就是去官网找相应的资料了:echarts官网 ,里面有教程有API。先拷贝一下官方的教程:5分钟上手ECharts获取ECharts你可以通过以下几种方式获取ECharts... 查看详情

pytorch模型训练实用教程学习笔记:二模型的构建(代码片段)

...Pytorch官方文档的各种API是根据字母排列的,并不适合学习阅读。于是在gayhub上找到了这样一份教程《Pytorch模型训练实用教程》,写得不错,特此根据它来再学习一下Pytorch。仓库地址:https://github.com/TingsongYu/PyTorch... 查看详情

kryo官方文档学习笔记(代码片段)

一.官方文档Kryo目前更新到5.0版本: https://github.com/EsotericSoftware/kryo4.0版本中文翻译: https://blog.csdn.net/fanjunjaden/article/details/72823866?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EC 查看详情

pcl——pcl库的简单使用(代码片段)

...关概念,更多请见下面几篇文章:Apollo星火计划学习笔记——第六讲上自动驾驶感知基础(I)自动驾驶感知——激光雷达物体检测算法自动驾驶感知——激光雷达基本概念|激光雷达点云|激光雷达的标定1.1激光雷... 查看详情

tenseal学习笔记一(代码片段)

...nSEALContextEncryptionandEvaluation引言发现网上没有什么TenSEAL的学习笔记,只能看官方文档,所以打算根据官方文档和自己的一些理解写一下TenSEAL的学习笔记。TenSEAL简介Tutorial0:GettingStartedWelcometoTenSEA 查看详情

pytorch模型训练实用教程学习笔记:一数据加载和transforms方法总结(代码片段)

...Pytorch官方文档的各种API是根据字母排列的,并不适合学习阅读。于是在gayhub上找到了这样一份教程《Pytorch模型训练实用教程》,写得不错,特此根据它来再学习一下Pytorch。仓库地址:https://github.com/TingsongYu/PyTorch... 查看详情

httpurlconnection学习笔记-百度内容审核-图像(代码片段)

HttpURLConnection学习笔记-百度内容审核-图像代码1.官方的例子2.自己的学习代码参考资料用到百度内容审核-图像看了官方的工作包中使用HttpURLConnection请求,封装好的工具类用习惯了,很少看里面,撞上了就学习一下吧... 查看详情