pcl中计算VFH特征,以及进行特征匹配,计算VFH描述子之间的欧式距离

在聚类分割后,会产生多个pcd文件,我们需要从中找出目标pcd,此时,就可以使用VFH(视点特征直方图),它先计算聚类分割产生的每个pcd的VFH,然后将每个VFH与特征库中的VFH比较(特征库就是目标pcd的VFH)。比较方式为计算两者VFH描述子的欧式距离,距离越小,说明两个VFH相关性越大,即两个pcd文件最相似,从而找出聚类分割后的目标pcd文件。代码如下:

包含头文件:

#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_cloud.h>
#include <pcl/features/vfh.h>
#include <pcl/features/normal_3d.h>
#include <pcl/features/integral_image_normal.h>
#include <pcl/visualization/pcl_plotter.h>
#include <iostream>
#include <string>
#include <cmath>
#include <cstdio>

using namespace std;
  1. 计算VFH特征

两个参数分别为:cloud指向点云文件的点云指针,vfh_dir为生成的VFH类型的pcd的存储路径

void VFH(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, string vfh_dir){
    //计算点云的VFH
    pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree1(new pcl::search::KdTree<pcl::PointXYZ>());
    ne.setInputCloud(cloud);
    ne.setSearchMethod(tree1);
    ne.setRadiusSearch(0.01);

    pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
    ne.compute(*normals);


    pcl::VFHEstimation<pcl::PointXYZ, pcl::Normal, pcl::VFHSignature308> vfh;
    vfh.setInputCloud(cloud);
    vfh.setInputNormals(normals);

    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree2(new pcl::search::KdTree<pcl::PointXYZ>());
    vfh.setSearchMethod(tree2);
    pcl::PointCloud<pcl::VFHSignature308>::Ptr vfh_ptr(new pcl::PointCloud<pcl::VFHSignature308>());
    vfh.compute(*vfh_ptr);//计算特征值,这是一组特征值
    //cout << vfh_ptr->size() << endl;
    pcl::io::savePCDFile(vfh_dir, *vfh_ptr, false);//将特征值保存
    //显示
    /*pcl::visualization::PCLPlotter plotter;
    plotter.addFeatureHistogram(*vfh_ptr, 200);
    plotter.plot();*/
}

2、VFH特征匹配,通过计算欧式距离来匹配目标文件

void feature_matching(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,int file_count, string file_dir, string vfh_dir) {
    //计算不同点云描述子(特征向量)之间的欧式距离
    /* 参数介绍
    cloud:指向点云文件的指针
    file_count:聚类分割产生的点云文件数量
    file_dir:聚类分割产生的点云文件存储路径
    vfh_dir:VFH存储路径*/
    pcl::PointCloud<pcl::VFHSignature308>::Ptr vfh_lib(new pcl::PointCloud<pcl::VFHSignature308>());
    pcl::PointCloud<pcl::VFHSignature308>::Ptr vfh_ptr(new pcl::PointCloud<pcl::VFHSignature308>());
    double thresh = 15; //设置阈值
    string file_dir1, vfh_dir1;
    int count = 0;//记录符合要求的pcd
    if (-1 == pcl::io::loadPCDFile("C:\\pcd\\library\\1902.pcd", *vfh_lib)) {
        cout << "load pcd file failed. please check it." << endl;
        return;
    }
    for (int j = 1; j <= file_count; j++) {
        file_dir1 = file_dir + to_string(j) + ".pcd";
        if (-1 == pcl::io::loadPCDFile(file_dir1, *cloud)) {
            cout << "load pcd file failed. please check it." << endl;
            return;
        }
        vfh_dir1 = vfh_dir + to_string(j) + ".pcd";
        VFH(cloud, vfh_dir1);
        if (-1 == pcl::io::loadPCDFile(vfh_dir1, *vfh_ptr)) {
            cout << "load pcd file failed. please check it." << endl;
            return;
        }
        double dist = 0; //存最终的距离
        for (int i = 0; i < 308; i++) {
            dist = dist + (static_cast<double>(vfh_lib->points[0].histogram[i]) - static_cast<double>(vfh_ptr->points[0].histogram[i])) * (static_cast<double>(vfh_lib->points[0].histogram[i]) - static_cast<double>(vfh_ptr->points[0].histogram[i]));
        }
        dist = sqrt(dist);
        cout << "特征值之间的欧氏距离" << dist << endl;
        if (dist > thresh) {
            //删除不符合的pcd文件以及vfh
            const char* savePath1 = file_dir1.c_str();
            const char* savePath2 = vfh_dir1.c_str();

            if (remove(savePath1) == 0 && remove(savePath2) == 0)
            {
                cout << "删除成功" << endl;
            }
            else
            {
                cout << "删除失败" << endl;
            }
        }
        else {
            count = j;//取得目标文件索引
        }
    }
    file_dir1 = file_dir + to_string(count) + ".pcd";
    if (-1 == pcl::io::loadPCDFile(file_dir1, *cloud)) {
        cout << "load pcd file failed. please check it." << endl;
        return;
    }
}
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个使用PCLVFH算法加汉明特征匹配的简单示例代码: ```cpp #include <iostream> #include <pcl/io/pcd_io.h> #include <pcl/point_types.h> #include <pcl/features/vfh.h> #include <pcl/features/normal_3d.h> #include <pcl/registration/correspondence_estimation.h> #include <pcl/registration/correspondence_rejection_sample_consensus.h> #include <pcl/registration/transformation_estimation_svd.h> int main(int argc, char** argv) { // 加载点云数据 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_source(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_target(new pcl::PointCloud<pcl::PointXYZ>); pcl::io::loadPCDFile("source.pcd", *cloud_source); pcl::io::loadPCDFile("target.pcd", *cloud_target); // 计算法向量 pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne; ne.setInputCloud(cloud_source); pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>()); ne.setSearchMethod(tree); pcl::PointCloud<pcl::Normal>::Ptr normals_source(new pcl::PointCloud<pcl::Normal>); ne.setRadiusSearch(0.03); ne.compute(*normals_source); ne.setInputCloud(cloud_target); pcl::PointCloud<pcl::Normal>::Ptr normals_target(new pcl::PointCloud<pcl::Normal>); ne.compute(*normals_target); // 计算VFH描述 pcl::VFHEstimation<pcl::PointXYZ, pcl::Normal, pcl::VFHSignature308> vfh; vfh.setInputCloud(cloud_source); vfh.setInputNormals(normals_source); pcl::search::KdTree<pcl::PointXYZ>::Ptr vfhtree(new pcl::search::KdTree<pcl::PointXYZ>()); vfh.setSearchMethod(vfhtree); pcl::PointCloud<pcl::VFHSignature308>::Ptr vfhs_source(new pcl::PointCloud<pcl::VFHSignature308>); vfh.compute(*vfhs_source); vfh.setInputCloud(cloud_target); vfh.setInputNormals(normals_target); pcl::PointCloud<pcl::VFHSignature308>::Ptr vfhs_target(new pcl::PointCloud<pcl::VFHSignature308>); vfh.compute(*vfhs_target); // 计算VFH描述的汉明距离 pcl::registration::CorrespondenceEstimation<pcl::VFHSignature308, pcl::VFHSignature308> est; est.setInputSource(vfhs_source); est.setInputTarget(vfhs_target); pcl::CorrespondencesPtr correspondences(new pcl::Correspondences()); est.determineCorrespondences(*correspondences); // 筛选和优化对应关系 pcl::registration::CorrespondenceRejectorSampleConsensus<pcl::PointXYZ> rejector; rejector.setInputSource(cloud_source); rejector.setInputTarget(cloud_target); rejector.setInlierThreshold(0.15); rejector.setMaximumIterations(10000); pcl::CorrespondencesPtr correspondences_filtered(new pcl::Correspondences()); rejector.getRemainingCorrespondences(*correspondences, *correspondences_filtered); // 计算变换矩阵 pcl::registration::TransformationEstimationSVD<pcl::PointXYZ, pcl::PointXYZ> estimation; pcl::registration::TransformationEstimationSVD<pcl::PointXYZ, pcl::PointXYZ>::Matrix4 transformation; estimation.estimateRigidTransformation(*cloud_source, *cloud_target, *correspondences_filtered, transformation); // 输出结果 std::cout << "Transformation matrix:" << std::endl; std::cout << transformation << std::endl; return 0; } ``` 该代码,先加载了两个点云数据,然后计算了每个点的法向量和VFH描述。接着,使用pcl::registration::CorrespondenceEstimation类计算点云间的对应关系,并使用pcl::registration::CorrespondenceRejectorSampleConsensus类对对应关系进行筛选和优化,最后使用pcl::registration::TransformationEstimationSVD类计算点云间的变换矩阵。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值