点云处理系列 - 点云特征提取

1. 点云特征与关键点的区别?

关键点提取关键的一些点,旨在减少数据量;而特征提取旨在为每个点提供一个可用于后续任务的描述。

通常点云特征与关键点结合使用。

2. 特征提取算法

注意: 本数据单位为mm,通常数据单位为m,取半径之类得参数要除1000

  • 法线估计 : 每一个点的位置都有垂直于点表面的的矢量,但是这种方式比较耗时

  • SHOT

  • PFH 点特征直方图

  • FPFH 快速点特征直方图

  • VFH

2.1. 法线估计

每一个点的位置都有垂直于点表面的的矢量,但是这种方式比较耗时。

2.1.1. PCL 中的实例

#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/features/normal_3d.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/kdtree/kdtree_flann.h>

int main() 
{
    // 1. Load Point Cloud from PCD file
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>());
    pcl::io::loadPCDFile("second_radius_cloud.pcd", *cloud);

    // 2. Setup the normal estimation
    pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimation;
    normal_estimation.setInputCloud(cloud);
    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
    normal_estimation.setSearchMethod(tree);
    normal_estimation.setRadiusSearch(30);
    
    // 3. Compute the normals
    pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>());
    normal_estimation.compute(*normals);

    // 4. Visualization
    pcl::visualization::PCLVisualizer viewer("Normals Viewer");
    viewer.setBackgroundColor(0, 0, 0);
    viewer.addPointCloud<pcl::PointXYZ>(cloud, "cloud");
    viewer.addPointCloudNormals<pcl::PointXYZ, pcl::Normal>(cloud, normals, 10, 50, "normals");
    viewer.initCameraParameters();
    viewer.saveScreenshot("screenshot.png");
    viewer.spin();

    return 0;
    
}

在这里插入图片描述

2.2. SHOT

每一个点的位置都有垂直于点表面的的矢量,但是这种方式比较耗时。

2.2.1. PCL 中的实例

在这里可视化了shot的前三个维度。


#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/features/normal_3d.h>
#include <pcl/features/shot.h>
#include <pcl/visualization/pcl_visualizer.h>

int main() 
{
    // Load Point Cloud from PCD file
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>());
    pcl::io::loadPCDFile("second_radius_cloud.pcd", *cloud);

    // Compute Normals
    pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimation;
    pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>());
    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
    normal_estimation.setInputCloud(cloud);
    normal_estimation.setSearchMethod(tree);
    normal_estimation.setRadiusSearch(30);
    normal_estimation.compute(*normals);

    // Compute SHOT descriptors
    pcl::SHOTEstimation<pcl::PointXYZ, pcl::Normal, pcl::SHOT352> shot;
    pcl::PointCloud<pcl::SHOT352>::Ptr shot_descriptors(new pcl::PointCloud<pcl::SHOT352>());
    shot.setInputCloud(cloud);
    shot.setInputNormals(normals);
    shot.setRadiusSearch(3);
    shot.compute(*shot_descriptors);
    
    // Convert SHOT values to colors
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr colored_cloud(new pcl::PointCloud<pcl::PointXYZRGB>());
    colored_cloud->resize(cloud->size());
    for (size_t i = 0; i < cloud->size(); ++i)
    {
        pcl::PointXYZRGB point;
        point.x = (*cloud)[i].x;
        point.y = (*cloud)[i].y;
        point.z = (*cloud)[i].z;

        // Use the first three dimensions of the SHOT descriptor to color the point
        point.r = static_cast<uint8_t>(255 * std::min(1.0f, shot_descriptors->points[i].descriptor[0]));
        point.g = static_cast<uint8_t>(255 * std::min(1.0f, shot_descriptors->points[i].descriptor[1]));
        point.b = static_cast<uint8_t>(255 * std::min(1.0f, shot_descriptors->points[i].descriptor[2]));

        colored_cloud->points[i] = point;
    }
    
    // Visualization
    pcl::visualization::PCLVisualizer viewer("SHOT Features Viewer");
    viewer.setBackgroundColor(0, 0, 0);
    viewer.addPointCloud<pcl::PointXYZRGB>(colored_cloud, "colored cloud"););
    viewer.spin();

    return 0;
}


在这里插入图片描述

2.3. PFH 点特征直方图

PFH (Point Feature Histograms, PFH,点特征直方图) 通过参数化查询点与邻域点之间的空间差异,并形成一个多维直方图对点的k邻域几何属性进行描述。直方图所在的高维超空间为特征表示提供了一个可度量的信息空间,对点云对应曲面的6维姿态来说它具有不变性,并且在不同的采样密度或邻域的噪音等级下具有鲁棒性。点特征直方图(PFH)表示法是基于点与其k邻域之间的关系以及它们的估计法线,简言之,它考虑估计法线方向之间所有的相互作用,试图捕获最好的样本表面变化情况,以描述样本的几何特征。

2.3.1. PCL 中的实例

#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/features/normal_3d.h>
#include <pcl/features/pfh.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/visualization/pcl_visualizer.h>

int main() 
{
    // 1. Load Point Cloud from PCD file
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>());
    pcl::io::loadPCDFile("second_radius_cloud.pcd", *cloud);

    // 2. Compute the normals
    pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimation;
    normal_estimation.setInputCloud(cloud);
    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
    normal_estimation.setSearchMethod(tree);
    normal_estimation.setRadiusSearch(30);
    pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>());
    normal_estimation.compute(*normals);
    // 3. Compute PFH descriptors
    pcl::PFHEstimation<pcl::PointXYZ, pcl::Normal, pcl::PFHSignature125> pfh_estimation;
    pfh_estimation.setInputCloud(cloud);
    pfh_estimation.setInputNormals(normals);
    pfh_estimation.setSearchMethod(tree);
    pfh_estimation.setRadiusSearch(80);
    pcl::PointCloud<pcl::PFHSignature125>::Ptr pfhs(new pcl::PointCloud<pcl::PFHSignature125>());
    pfh_estimation.compute(*pfhs);
    // 4. Convert PFH values to colors for visualization
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr colored_cloud(new pcl::PointCloud<pcl::PointXYZRGB>());
    colored_cloud->resize(cloud->size());
    for (size_t i = 0; i < cloud->size(); ++i) {
        pcl::PointXYZRGB point;
        point.x = (*cloud)[i].x;
        point.y = (*cloud)[i].y;
        point.z = (*cloud)[i].z;

        // Use the first dimension of the PFH descriptor to color the point
        point.r = static_cast<uint8_t>(255 * std::min(1.0f, pfhs->points[i].histogram[0] / 100.0f));
        point.g = 0;
        point.b = 0;

        colored_cloud->points[i] = point;
    }
    // 5. Visualization
    pcl::visualization::PCLVisualizer viewer("PFH Visualization");
    viewer.setBackgroundColor(0, 0, 0);
    viewer.addPointCloud<pcl::PointXYZRGB>(colored_cloud, "colored cloud");
    viewer.spin();
    return 0;
}


2.4. FPFH 快速点特征直方图
2.4.1. PCL 中的实例

快速点特征直方图(Fast Point Feature Histograms, FPFH)是PFH计算方式的简化形式。它的思想在于分别计算查询点的k邻域中每一个点的简化点特征直方图(Simplified Point Feature Histogram,SPFH),再通过一个公式将所有的SPFH加权成最后的快速点特征直方图。FPFH把算法的计算复杂度降低到了O(nk) ,但是仍然保留了PFH大部分的识别特性。


#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/features/normal_3d.h>
#include <pcl/features/fpfh.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/visualization/pcl_visualizer.h>

int main() {
    // 1. Load Point Cloud from PCD file
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>());
    pcl::io::loadPCDFile("second_radius_cloud.pcd", *cloud);

    // 2. Compute the normals
    pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimation;
    normal_estimation.setInputCloud(cloud);
    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
    normal_estimation.setSearchMethod(tree);
    normal_estimation.setRadiusSearch(300);
    pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>());
    normal_estimation.compute(*normals);

    // 3. Compute FPFH descriptors
    pcl::FPFHEstimation<pcl::PointXYZ, pcl::Normal, pcl::FPFHSignature33> fpfh_estimation;
    fpfh_estimation.setInputCloud(cloud);
    fpfh_estimation.setInputNormals(normals);
    fpfh_estimation.setSearchMethod(tree);
    fpfh_estimation.setRadiusSearch(500);
    pcl::PointCloud<pcl::FPFHSignature33>::Ptr fpfhs(new pcl::PointCloud<pcl::FPFHSignature33>());
    fpfh_estimation.compute(*fpfhs);

    // 4. Convert FPFH values to colors for visualization
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr colored_cloud(new pcl::PointCloud<pcl::PointXYZRGB>());
    colored_cloud->resize(cloud->size());
    for (size_t i = 0; i < cloud->size(); ++i) {
        pcl::PointXYZRGB point;
        point.x = (*cloud)[i].x;
        point.y = (*cloud)[i].y;
        point.z = (*cloud)[i].z;

        // Use the first dimension of the FPFH descriptor to color the point
        point.r = static_cast<uint8_t>(255 * std::min(1.0f, fpfhs->points[i].histogram[0] / 100.0f));
        point.g = 0;
        point.b = 0;

        colored_cloud->points[i] = point;
    }

    // 5. Visualization
    boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("FPFH Visualization"));
    viewer->setBackgroundColor(0, 0, 0);
    viewer->addPointCloud<pcl::PointXYZRGB>(colored_cloud, "colored cloud");
    viewer->spin();

    return 0;
}


2.5. VFH

FPFH有很好的速度和辨别能力,VFH在此基础上添加视点方差,同时保持尺度不变性。

2.5.1. PCL 中的实例

#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/features/normal_3d.h>
#include <pcl/features/vfh.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <sstream>

int main()
 {
 
    // 1. Load Point Cloud from PCD file
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>());
    pcl::io::loadPCDFile("second_radius_cloud.pcd", *cloud);

    // 2. Compute the normals
    pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimation;
    normal_estimation.setInputCloud(cloud);
    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
    normal_estimation.setSearchMethod(tree);
    normal_estimation.setRadiusSearch(30);
    pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>());
    normal_estimation.compute(*normals);

    // 3. Compute VFH descriptors
    pcl::VFHEstimation<pcl::PointXYZ, pcl::Normal, pcl::VFHSignature308> vfh_estimation;
    vfh_estimation.setInputCloud(cloud);
    vfh_estimation.setInputNormals(normals);
    vfh_estimation.setSearchMethod(tree);
    pcl::PointCloud<pcl::VFHSignature308>::Ptr vfhs(new pcl::PointCloud<pcl::VFHSignature308>());
    vfh_estimation.compute(*vfhs);

    // 4. Visualization
    boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("VFH Visualization"));
    viewer->setBackgroundColor(0, 0, 0);
    viewer->addPointCloud<pcl::PointXYZ>(cloud, "cloud");

    // Display some VFH dimensions as text
    for (size_t i = 0; i < 5; ++i) {
        std::stringstream ss;
        ss << "VFH value at dim " << i << ": " << vfhs->points[0].histogram[i];
        viewer->addText(ss.str(), 10, 20 + i * 20, 20, 1.0, 1.0, 1.0, "vfh_val" + std::to_string(i));
    }
    viewer->spin();

    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Adunn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值