以下是基于PCL库的点云处理流程,包括点云关键点提取,特征描述,一致性估计和精配准。

  1. 点云关键点提取

点云关键点提取是指从点云中提取出代表点云特征的关键点。PCL库提供了多种点云关键点提取算法,包括Harris Keypoint,ISS Keypoint,SIFT Keypoint等。

以ISS Keypoint为例,代码如下:

pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
// 读取点云数据

pcl::ISSKeypoint3D<pcl::PointXYZ, pcl::PointXYZ> iss_detector;
iss_detector.setInputCloud(cloud);
iss_detector.setSalientRadius(6 * resolution); // 设置感兴趣区域大小
iss_detector.setNonMaxRadius(4 * resolution); // 设置非极大值抑制区域大小
iss_detector.setThreshold21(0.975); // 设置第二个曲率阈值
iss_detector.setThreshold32(0.975); // 设置第三个曲率阈值
iss_detector.setMinNeighbors(5); // 设置最小邻居数
iss_detector.compute(*keypoints); // 计算关键点
  1. 特征描述

特征描述是指对点云关键点进行描述,以便后续进行匹配。PCL库提供了多种特征描述算法,包括FPFH,SHOT,VFH等。

以FPFH为例,代码如下:

pcl::PointCloud<pcl::FPFHSignature33>::Ptr features(new pcl::PointCloud<pcl::FPFHSignature33>);
pcl::FPFHEstimation<pcl::PointXYZ, pcl::Normal, pcl::FPFHSignature33> fpfh;
pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
// 计算点云法向量

fpfh.setInputCloud(keypoints);
fpfh.setInputNormals(normals);
fpfh.setRadiusSearch(2 * resolution); // 设置搜索半径
fpfh.compute(*features); // 计算特征描述子
  1. 一致性估计

一致性估计是指对点云匹配结果进行评估,以确定匹配结果的可靠性。PCL库提供了多种一致性估计算法,包括Sample Consensus Initial Alignment(SAC-IA),Sample Consensus Prerejective(SAC-PR)等。

以SAC-IA为例,代码如下:

pcl::SampleConsensusInitialAlignment<pcl::PointXYZ, pcl::PointXYZ, pcl::FPFHSignature33> sac_ia;
sac_ia.setInputSource(keypoints_src);
sac_ia.setInputTarget(keypoints_tgt);
sac_ia.setSourceFeatures(features_src);
sac_ia.setTargetFeatures(features_tgt);
sac_ia.setMaximumIterations(1000); // 设置最大迭代次数
sac_ia.setEuclideanFitnessEpsilon(1e-6); // 设置收敛阈值
sac_ia.align(*aligned_keypoints); // 进行初始配准

if (sac_ia.hasConverged()) {
    std::cout << "SAC-IA converged!" << std::endl;
}
  1. 精配准

精配准是指对点云进行最终的配准,以获得更高精度的匹配结果。PCL库提供了多种精配准算法,包括Iterative Closest Point(ICP),Generalized Iterative Closest Point(GICP)等。

以ICP为例,代码如下:

pcl::IterativeClosestPoint<pcl::PointXYZ, pcl::PointXYZ> icp;
icp.setInputSource(cloud_src);
icp.setInputTarget(cloud_tgt);
icp.setMaxCorrespondenceDistance(2 * resolution); // 设置最大对应距离
icp.setMaximumIterations(100); // 设置最大迭代次数
icp.setTransformationEpsilon(1e-6); // 设置收敛阈值
icp.align(*aligned_cloud); // 进行精配准

if (icp.hasConverged()) {
    std::cout << "ICP converged!" << std::endl;
}

完整代码如下:

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/keypoints/iss_3d.h>
#include <pcl/features/fpfh.h>
#include <pcl/registration/sample_consensus_initial_alignment.h>
#include <pcl/registration/icp.h>

int main(int argc, char** argv) {
    if (argc != 3) {
        std::cerr << "Usage: " << argv[0] << " source.pcd target.pcd" << std::endl;
        return -1;
    }

    float resolution = 0.01f; // 设置分辨率

    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_src(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_tgt(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<pcl::PointXYZ>::Ptr aligned_cloud(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<pcl::PointXYZ>::Ptr keypoints_src(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<pcl::PointXYZ>::Ptr keypoints_tgt(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<pcl::PointXYZ>::Ptr aligned_keypoints(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<pcl::FPFHSignature33>::Ptr features_src(new pcl::PointCloud<pcl::FPFHSignature33>);
    pcl::PointCloud<pcl::FPFHSignature33>::Ptr features_tgt(new pcl::PointCloud<pcl::FPFHSignature33>);

    pcl::io::loadPCDFile(argv[1], *cloud_src);
    pcl::io::loadPCDFile(argv[2], *cloud_tgt);

    pcl::ISSKeypoint3D<pcl::PointXYZ, pcl::PointXYZ> iss_detector;
    iss_detector.setInputCloud(cloud_src);
    iss_detector.setSalientRadius(6 * resolution);
    iss_detector.setNonMaxRadius(4 * resolution);
    iss_detector.setThreshold21(0.975);
    iss_detector.setThreshold32(0.975);
    iss_detector.setMinNeighbors(5);
    iss_detector.compute(*keypoints_src);

    iss_detector.setInputCloud(cloud_tgt);
    iss_detector.compute(*keypoints_tgt);

    pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
    pcl::PointCloud<pcl::Normal>::Ptr normals_src(new pcl::PointCloud<pcl::Normal>);
    pcl::PointCloud<pcl::Normal>::Ptr normals_tgt(new pcl::PointCloud<pcl::Normal>);

    ne.setSearchMethod(tree);
    ne.setInputCloud(cloud_src);
    ne.setRadiusSearch(2 * resolution);
    ne.compute(*normals_src);

    ne.setInputCloud(cloud_tgt);
    ne.compute(*normals_tgt);

    pcl::FPFHEstimation<pcl::PointXYZ, pcl::Normal, pcl::FPFHSignature33> fpfh;
    fpfh.setInputCloud(keypoints_src);
    fpfh.setInputNormals(normals_src);
    fpfh.setRadiusSearch(2 * resolution);
    fpfh.compute(*features_src);

    fpfh.setInputCloud(keypoints_tgt);
    fpfh.setInputNormals(normals_tgt);
    fpfh.compute(*features_tgt);

    pcl::SampleConsensusInitialAlignment<pcl::PointXYZ, pcl::PointXYZ, pcl::FPFHSignature33> sac_ia;
    sac_ia.setInputSource(keypoints_src);
    sac_ia.setInputTarget(keypoints_tgt);
    sac_ia.setSourceFeatures(features_src);
    sac_ia.setTargetFeatures(features_tgt);
    sac_ia.setMaximumIterations(1000);
    sac_ia.setEuclideanFitnessEpsilon(1e-6);
    sac_ia.align(*aligned_keypoints);

    pcl::IterativeClosestPoint<pcl::PointXYZ, pcl::PointXYZ> icp;
    icp.setInputSource(cloud_src);
    icp.setInputTarget(cloud_tgt);
    icp.setMaxCorrespondenceDistance(2 * resolution);
    icp.setMaximumIterations(100);
    icp.setTransformationEpsilon(1e-6);
    icp.align(*aligned_cloud);

    if (sac_ia.hasConverged()) {
        std::cout << "SAC-IA converged!" << std::endl;
    }

    if (icp.hasConverged()) {
        std::cout << "ICP converged!" << std::endl;
    }

    pcl::io::savePCDFileBinary("aligned_keypoints.pcd", *aligned_keypoints);
    pcl::io::savePCDFileBinary("aligned_cloud.pcd", *aligned_cloud);

    return 0;
}
``

原文地址: http://www.cveoy.top/t/topic/crWv 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录