PCL 最远点采样(FPS)

news2024/11/18 15:41:53

目录

一、概述

1.1原理

1.2实现步骤

1.3应用场景

二、代码实现

2.1关键函数

2.1.1 可视化函数

2.1.2 最远点采样

2.2完整代码

三、实现效果


PCL点云算法汇总及实战案例汇总的目录地址链接:

PCL点云算法与项目实战案例汇总(长期更新)


一、概述

        最远点采样(FPS) 是一种常用的点云降采样方法,旨在从原始点云中选择一组具有代表性的点,以保持点云的几何特征。该方法通过每次选择距离已选定点最远的点,从而实现均匀分布的采样。

1.1原理

        最远点采样的基本思想是:在每次迭代中,从未选中的点中选择一个与已选点集中距离最远的点。通过这种方式,可以确保所选点在空间上的分布尽可能均匀。这种方法特别适用于处理大规模点云数据

1.2实现步骤

  1. 读取点云数据。
  2. 初始化选定点集合,设置采样数量。
  3. 在未选中的点中找到距离已选点最远的点并添加到选定点集合中。
  4. 可视化原始点云和采样后的点云。

1.3应用场景

  1. 点云简化:在保留几何特征的情况下减少点云的数量。
  2. 特征提取:从点云中提取具有代表性的特征点。
  3. 实时处理:在需要快速处理的场景中使用降采样的点云。

二、代码实现

2.1关键函数

2.1.1 可视化函数

通过设置不同的视口和背景颜色,分别显示原始点云和采样后的点云。

// 可视化原始点云和采样后的点云
void visualizePointClouds(
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,  // 原始点云
    pcl::PointCloud<pcl::PointXYZ>::Ptr sampled_cloud)  // 采样后的点云
{
    // 创建可视化器
    boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("ShowCloud"));

    // 创建视口1,显示原始点云
    int vp_1;
    viewer->createViewPort(0.0, 0.0, 0.5, 1.0, vp_1);  // 创建左侧窗口
    viewer->setBackgroundColor(1.0, 1.0, 1.0, vp_1);  // 设置白色背景
    viewer->addText("Raw Point Clouds", 10, 10, "v1_text", vp_1);  // 添加标题

    // 创建视口2,显示采样后的点云
    int vp_2;
    viewer->createViewPort(0.5, 0.0, 1.0, 1.0, vp_2);  // 创建右侧窗口
    viewer->setBackgroundColor(0.98, 0.98, 0.98, vp_2);  // 设置浅灰色背景
    viewer->addText("FPS Point Clouds", 10, 10, "v2_text", vp_2);  // 添加标题

    // 添加点云到视口
    viewer->addPointCloud<pcl::PointXYZ>(cloud, "sample cloud", vp_1);  // 添加原始点云
    viewer->addPointCloud<pcl::PointXYZ>(sampled_cloud, "cloud_filtered", vp_2);  // 添加采样后的点云
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1, 0, 0, "sample cloud", vp_1);  // 设置颜色为红色
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0, 1, 0, "cloud_filtered", vp_2);  // 设置颜色为绿色

    // 启动可视化循环
    while (!viewer->wasStopped())
    {
        viewer->spinOnce(100);  // 刷新可视化器
        boost::this_thread::sleep(boost::posix_time::microseconds(100000));  // 睡眠以避免CPU占用过高
    }
}

2.1.2 最远点采样

使用 PCL 提供的 FarthestPointSampling 类进行最远点采样,并设置相关参数。

注:该函数为PCL1.13.0新增

// 最远点采样
pcl::PointCloud<pcl::PointXYZ>::Ptr farthestPointSampling(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, int sample_size)
{
    pcl::PointCloud<pcl::PointXYZ>::Ptr sampled_cloud(new pcl::PointCloud<pcl::PointXYZ>);  // 存储采样后的点云
    std::unordered_set<int> sampled_indices;  // 用于存储已选择点的索引

    // 随机选择第一个点
    int first_index = rand() % cloud->points.size();
    sampled_indices.insert(first_index);  // 添加到已选择集合
    sampled_cloud->points.push_back(cloud->points[first_index]);  // 添加到采样点云

    // 进行采样,直到达到指定数量
    while (sampled_cloud->points.size() < sample_size)
    {
        std::vector<float> distances(cloud->points.size(), std::numeric_limits<float>::max());  // 初始化距离向量
        for (const auto& index : sampled_indices)
        {
            for (size_t i = 0; i < cloud->points.size(); ++i)
            {
                if (sampled_indices.find(i) == sampled_indices.end())  // 确保点没有被选择
                {
                    float distance = euclideanDistance(cloud->points[index], cloud->points[i]); // 计算距离
                    distances[i] = std::min(distances[i], distance);  // 更新最小距离
                }
            }
        }

        // 找到距离最远的点
        int farthest_index = std::distance(distances.begin(), std::max_element(distances.begin(), distances.end()));
        sampled_indices.insert(farthest_index);  // 将该点添加到已选择点集
        sampled_cloud->points.push_back(cloud->points[farthest_index]);  // 添加到采样点云
    }
    
    sampled_cloud->width = sampled_cloud->points.size();  // 更新宽度
    sampled_cloud->height = 1;  // 设置高度
    sampled_cloud->is_dense = true;  // 确保点云是密集的

    return sampled_cloud;  // 返回采样后的点云
}

2.2完整代码

// C++头文件
#include <cmath>
#include <random>
// PCL头文件
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/filters/farthest_point_sampling.h> // 最远点采样
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>

// 可视化原始点云和采样后的点云
void visualizePointClouds(
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,  // 原始点云
    pcl::PointCloud<pcl::PointXYZ>::Ptr sampled_cloud)  // 采样后的点云
{
    // 创建可视化器
    boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("cloud"));

    // 创建视口1,显示原始点云
    int vp_1;
    viewer->createViewPort(0.0, 0.0, 0.5, 1.0, vp_1);  // 创建左侧窗口
    viewer->setBackgroundColor(0, 0, 0, vp_1);  // 设置黑色背景
    viewer->addText("Raw point clouds", 10, 10, "v1_text", vp_1);  // 添加标题

    // 创建视口2,显示采样后的点云
    int vp_2;
    viewer->createViewPort(0.5, 0.0, 1.0, 1.0, vp_2);  // 创建右侧窗口
    viewer->setBackgroundColor(0.1, 0.1, 0.1, vp_2);  // 设置灰色背景
    viewer->addText("FPS point clouds", 10, 10, "v2_text", vp_2);  // 添加标题

    // 添加点云到视口
    viewer->addPointCloud<pcl::PointXYZ>(cloud, "sample cloud", vp_1);
    viewer->addPointCloud<pcl::PointXYZ>(sampled_cloud, "cloud_filtered", vp_2);
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1, 0, 0, "sample cloud", vp_1);  // 设置颜色为红色
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0, 1, 0, "cloud_filtered", vp_2);  // 设置颜色为绿色

    // 启动可视化循环
    while (!viewer->wasStopped())
    {
        viewer->spinOnce(100);  // 刷新可视化器
        boost::this_thread::sleep(boost::posix_time::microseconds(100000));  // 睡眠以避免CPU占用过高
    }
}

int main(int argc, char** argv)
{
    // ------------------------------读取点云数据---------------------------------
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    if (pcl::io::loadPCDFile("dragon.pcd", *cloud) < 0)
    {
        PCL_ERROR("Could not read file\n");
        return (-1);  // 返回错误
    }
    pcl::PointCloud<pcl::PointXYZ>::Ptr filtered(new pcl::PointCloud<pcl::PointXYZ>);

    // -------------------------------最远点采样---------------------------------
    std::random_device rd;
    int random_seed = rd();   // 随机选取一个点作为种子点
    int sampleNum = 10000;    // 采样点个数
    pcl::FarthestPointSampling<pcl::PointXYZ> fps;
    fps.setInputCloud(cloud); // 读取点云
    fps.setSeed(random_seed); // 设置第一个种子点
    fps.setSample(sampleNum); // 设置采样点个数
    fps.filter(*filtered);    // 进行采样


    // ------------------------------结果可视化----------------------------------
    visualizePointClouds(cloud, filtered);  // 调用可视化函数

    return (0);
}

三、实现效果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2184162.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

事务原理,以及MVCC如何实现RC,RR隔离级别的

事务原理 redo log 保持持久性&#xff1a; 首先原来的情况是我们做一组操作的时候&#xff0c;先去操作bufferpool缓冲区&#xff0c;如果没有&#xff0c;那么后台线程将数据页换入换出到缓冲区&#xff0c;然后我们对这个buffer pool进行修改&#xff0c;为脏页&#xff0c…

Redis篇(Redis原理 - 数据结构)(持续更新迭代)

目录 一、动态字符串 二、intset 三、Dict 1. 简介 2. Dict的扩容 3. Dict的rehash 4. 知识小结 四、ZipList 1. 简介 2. ZipListEntry 3. Encoding编码 五、ZipList的连锁更新问题 六、QuickList 七、SkipList 八、RedisObject 1. 什么是 redisObject 2. Redi…

开放式耳机哪个品牌好?2024年蓝牙耳机排行榜

开放式蓝牙耳机以其独树一帜的佩戴方式&#xff0c;正逐渐成为音乐爱好者和运动达人的新宠。时尚而又实用。如果你对传统耳机的佩戴方式感到厌倦&#xff0c;或者在寻找一款既能提供高品质音乐体验又能兼顾佩戴舒适性的耳机&#xff0c;那么开放式蓝牙耳机可能会是你的理想选择…

Vue3轻松实现前端打印功能

文章目录 1.前言2.安装配置2.1 下载安装2.2 main.js 全局配置3.综合案例3.1 设置打印区域3.2 绑定打印事件3.3 完整代码4.避坑4.1 打印表格无边框4.2 单选框复选框打印不选中4.3 去除页脚页眉4.4 打印內容不自动换行1.前言 vue3 前端打印功能主要通过插件来实现。 市面上常用的…

【CKA】八、扩容Deployment

8、扩容Deployment 1. 考题内容&#xff1a; 2. 答题思路&#xff1a; 直接使用命令扩容就行 我考的题只是把 loadbalancer 名字换了 &#xff0c;其他都一模一样 3. 官网地址&#xff1a; https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/deployment/ …

Golang | Leetcode Golang题解之第451题根据字符出现频率排序

题目&#xff1a; 题解&#xff1a; func frequencySort(s string) string {cnt : map[byte]int{}maxFreq : 0for i : range s {cnt[s[i]]maxFreq max(maxFreq, cnt[s[i]])}buckets : make([][]byte, maxFreq1)for ch, c : range cnt {buckets[c] append(buckets[c], ch)}an…

【AI大模型】深入Transformer架构:编码器部分的实现与解析(上)

目录 &#x1f354; 编码器介绍 &#x1f354; 掩码张量 2.1 掩码张量介绍 2.2 掩码张量的作用 2.3 生成掩码张量的代码分析 2.4 掩码张量的可视化 2.5 掩码张量总结 &#x1f354; 注意力机制 3.1 注意力计算规则的代码分析 3.2 带有mask的输入参数&#xff1a; 3.…

华为开源自研AI框架昇思MindSpore应用案例:计算高效的卷积模型ShuffleNet

如果你对MindSpore感兴趣&#xff0c;可以关注昇思MindSpore社区 ShuffleNet ShuffleNet网络介绍 ShuffleNetV1是旷视科技提出的一种计算高效的CNN模型&#xff0c;和MobileNet, SqueezeNet等一样主要应用在移动端&#xff0c;所以模型的设计目标就是利用有限的计算资源来达到…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《基于节点碳势响应的新型电力系统鲁棒优化调度 》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

生信初学者教程(二十二):Boruta+RF筛选候选标记物

文章目录 介绍加载R包导入数据准备数据机器学习特征筛选数据分割基础模型Boruta特征筛选调参最终分类模型测试集验证标记基因输出结果总结介绍 采用了Boruta结合 RF(Random Forest) 的方法,对差异基因(参考 @sec-different-limma) 进行了特征筛选。通过这种方法,能够从大…

你以为瀑布流布局很复杂?Vue-Waterfall让你秒变前端高手

你以为瀑布流布局很复杂&#xff1f;Vue-Waterfall让你秒变前端高手 Vue-Waterfall 是一个轻量级的 Vue.js 组件&#xff0c;专为实现灵活的瀑布流布局设计。如果你需要在页面上呈现动态、响应式的布局&#xff0c;那这个组件绝对能帮到你&#xff01;本文将带你快速了解这个组…

推荐 uniapp 相对好用的海报生成插件

插件地址&#xff1a;自定义canvas样式海报 - DCloud 插件市场 兼容性也是不错的&#xff1a;

微软准备了 Windows 11 24H2 ISO “OOBE/BypassNRO“命令依然可用

Windows 11 24H2 可能在未来几周内开始推出。 微软已经要求 OEM 遵循新的指南准备好 Windows 11 24H2 就绪的驱动程序&#xff0c;并且现在已经开始准备媒体文件 (.ISO)。 OEM ISO 的链接已在微软服务器上发布。 一个标有"X23-81971_26100.1742.240906-0331.ge_release_sv…

[Python学习日记-35] Python 中的内置函数(上)

[Python学习日记-35] Python 中的内置函数&#xff08;上&#xff09; 简介 内置函数详解&#xff08;A-E&#xff09; 简介 在 Python 中有很多内置函数&#xff0c;例如 len()&#xff0c;这些函数是 Python 解释器自带的&#xff0c;可以直接使用。本篇将介绍 A-H 的内置函…

基于Springboot+Vue的《计算机基础》网上考试系统(含源码数据库)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 系统中…

YOLOv11:重新定义实时目标检测的未来

YOLO 版本发布历史回顾 YOLO (You Only Look Once), a popular object detection and image segmentation model, was developed by Joseph Redmon and Ali Farhadi at the University of Washington. Launched in 2015, YOLO quickly gained popularity for its high speed a…

vulnhub-mrRobot靶机的测试报告

目录 一、测试环境 1、系统环境 2、使用工具/软件 二、测试目的 三、操作过程 1、信息搜集 2、渗透网页 3、Getshell 4、提权 四、结论 一、测试环境 1、系统环境 渗透机&#xff1a;kali2021.1(192.168.202.134) 靶 机&#xff1a;linux 3.13.0-55-generic #94-…

复习HTML(基础)

目录 HTML含义 HTML作用 HTML的常用元素 元素的特点 元素的分类 1 是否嵌套关系 2 是否独占一行 块元素&#xff1a;独占一行 行内元素&#xff1a;共享一行 行内元素与块级元素的转换 3是否有结束标签 常用标签 1 标题标签&#xff1a;有六级 我们用h1 ~h6 表…

国产化系统/鸿蒙开发足浴店收银源码-收缩左侧———未来之窗行业应用跨平台架构

一、左侧展开后 二、代码 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head><title></title><meta http-equiv"Content-Type" content"text/html; charsetUTF-8"><style t…

PHP安装后Apache无法运行的问题

问题 按照网上教程php安装点击跳转教程&#xff0c;然后修改Apache的httpd.conf文件&#xff0c;本来可以运行的Apache&#xff0c;无法运行了 然后在"C:\httpd-2.4.62-240904-win64-VS17\Apache24\logs\error.log"&#xff08;就是我下载Apache的目录下的logs中&am…