点云获取pcl点云以某个点云的已经分块得区域的交集

首先将点云分块得到区域后,获取每个块的box的最大最小点云,然后提取box内的点云。

                pcl::IndicesPtr indexes(new pcl::Indices());
                pcl::getPointsInBox(*cloud_1, min_pt, max_pt, *indexes);
                // --------------------------取框内和框外点------------------------------------
                pcl::ExtractIndices<PointType> extr;
                extr.setInputCloud(cloud);  // 设置输入点云
                extr.setIndices(indexes);   // 设置索引
                pcl::PointCloud<PointType>::Ptr cloud_in_box(new pcl::PointCloud<PointType>());
                extr.filter(*cloud_in_box); // 提取对应索引的点云
                cout << "方框内点的个数为:" << cloud_in_box->points.size() << endl;
                pcl::PointCloud<PointType>::Ptr cloud_out_box(new pcl::PointCloud<PointType>);
                extr.setNegative(true);    // 提取对应索引之外的点
                extr.filter(*cloud_out_box);
                cout << "方框外点的个数为:" << cloud_out_box->points.size() << endl;

但是不知道为什么每次提取的indexes都不对,提取的区域大部分都是包含整个点云的点,很奇怪。于是看了下提取box点云的源码

pcl::IndicesPtr indexes(new pcl::Indices());
                pcl::getPointsInBox(*cloud_1, min_pt, max_pt, *indexes);
//
template <typename PointT> inline void
pcl::getPointsInBox (const pcl::PointCloud<PointT> &cloud, 
                     Eigen::Vector4f &min_pt, Eigen::Vector4f &max_pt,
                     Indices &indices)
{
  indices.resize (cloud.size ());
  int l = 0;

  // If the data is dense, we don't need to check for NaN
  if (cloud.is_dense)
  {
    for (std::size_t i = 0; i < cloud.size (); ++i)
    {
      // Check if the point is inside bounds
      if (cloud[i].x < min_pt[0] || cloud[i].y < min_pt[1] || cloud[i].z < min_pt[2])
        continue;
      if (cloud[i].x > max_pt[0] || cloud[i].y > max_pt[1] || cloud[i].z > max_pt[2])
        continue;
      indices[l++] = int (i);
    }
  }
  // NaN or Inf values could exist => check for them
  else
  {
    for (std::size_t i = 0; i < cloud.size (); ++i)
    {
      // Check if the point is invalid
      if (!std::isfinite (cloud[i].x) || 
          !std::isfinite (cloud[i].y) || 
          !std::isfinite (cloud[i].z))
        continue;
      // Check if the point is inside bounds
      if (cloud[i].x < min_pt[0] || cloud[i].y < min_pt[1] || cloud[i].z < min_pt[2])
        continue;
      if (cloud[i].x > max_pt[0] || cloud[i].y > max_pt[1] || cloud[i].z > max_pt[2])
        continue;
      indices[l++] = int (i);
    }
  }
  indices.resize (l);
}

不知道为什么不行,但看到只是比价点的大小是否在box内,按照源码修改,完美解决。

//
// Created by wzs on 2024/6/6.
//

#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <stdlib.h> //rand()头文件
#include <pcl/io/pcd_io.h>
#include <pcl/octree/octree.h>
#include <boost/thread/thread.hpp>
#include <pcl/visualization/pcl_visualizer.h>

#include <pcl/filters/extract_indices.h>
#include <pcl/common/common.h>
#include "pcl/common/centroid.h"
#include "pcl/common/distances.h"

using namespace std;

typedef pcl::PointXYZ PointType;


int main()
{
    string path("../test_data/1/3.pcd");// 原始点云所在文件夹
    string outpath("../test_data/1/voxel_map");        // 分块保存路径文件夹名

    string path_1("../test_data/1/3_slope.pcd");
    string outpath_1("../test_data/1/voxel_map_1");        // 分块保存路径文件夹名

    string outpath_2("../test_data/1/voxel_map_2");        // 分块保存路径文件夹名

    float resolution = 1.0;        // 设置体素分辨率
    //-------------------------- 加载点云 --------------------------
    pcl::PointCloud<PointType>::Ptr cloud(new pcl::PointCloud<PointType>);
    if (pcl::io::loadPCDFile(path, *cloud) < 0)
    {
        PCL_ERROR("Couldn't read file \n");
//        system("pause");
        return -1;
    }

    pcl::PointCloud<PointType>::Ptr cloud_1(new pcl::PointCloud<PointType>);
    if (pcl::io::loadPCDFile(path_1, *cloud_1) < 0)
    {
        PCL_ERROR("cloud_slopen't read file \n");
//        system("pause");
        return -1;
    }

    // -----------------------获取分块点云保存路径----------------------------------
    printf("开始进行点云分块!!\n");
//    string::size_type iPos = path.find_last_of('//') + 1;
//    string filename = path.substr(iPos, path.length() - iPos);
//    string name = filename.substr(0, filename.rfind("."));
    // ---------------------使用八叉树快速构建体素索引------------------------------
    pcl::octree::OctreePointCloud<PointType> octree(resolution);
    octree.setInputCloud(cloud);
    octree.addPointsFromInputCloud(); // 从点云中构建八叉树
    pcl::Indices pointIdxVec;         // 体素内点的索引
    //-----------------------------开始分块-----------------------------------------
//    boost::shared_ptr<pcl::visualization::PCLVisualizer>viewer(new pcl::visualization::PCLVisualizer("planar segment")); ;
//    viewer->setBackgroundColor(0, 0, 0);
//    viewer->setWindowName("点云分块");
    pcl::PointCloud<PointType>::Ptr seg_cloud(new pcl::PointCloud<PointType>);
//    pcl::PointCloud<PointType>::Ptr seg_cloud_1(new pcl::PointCloud<PointType>);
//    pcl::PointCloud<PointType>::Ptr seg_cloud_1_0(new pcl::PointCloud<PointType>);

    int num_voxel = 0;
    for (auto iter = octree.leaf_breadth_begin(); iter != octree.leaf_breadth_end(); ++iter){
        num_voxel++;
    }
    float mean_voxel_size_ = cloud_1->size() / num_voxel;

    int begin = 0;
    // 构建八叉树叶子节点迭代器,遍历八叉树
    for (auto iter = octree.leaf_breadth_begin(); iter != octree.leaf_breadth_end(); ++iter)
    {
        auto key = iter.getCurrentOctreeKey(); // 获取当前迭代器八叉树节点的八叉树键
        auto it_key = octree.findLeaf(key.x, key.y, key.z); // 检查是否存在于八叉树中
        if (it_key != nullptr)
        {
            pointIdxVec.clear();
            //从八叉树叶子节点中获取单个叶子容器中的点索引
            pointIdxVec = iter.getLeafContainer().getPointIndicesVector();
            if (pointIdxVec.size() == 0) // 体素内点个数为0则跳过
            {
                continue;
            }else
            {

                seg_cloud->clear();
                
                std::stringstream ss;
                ss << outpath << "//"<< "_block_" << begin + 1 << ".pcd";
                pcl::copyPointCloud(*cloud, pointIdxVec, *seg_cloud);
                pcl::io::savePCDFileBinary(ss.str(), *seg_cloud);
                cout << "第[" << begin + 1 << "]块点云分割完毕!  " << seg_cloud->size() << "    " << mean_voxel_size_ << endl;

                pcl::PointCloud<PointType>::Ptr cloud_in_box(new pcl::PointCloud<PointType>());
                PointType point_min_, point_max_;
                pcl::getMinMax3D(*seg_cloud,point_min_,point_max_);
//                cout << "Min x: " << point_min_.x << endl;
//                cout << "Min y: " << point_min_.y << endl;
//                cout << "Min z: " << point_min_.z << endl;
//                cout << "Max x: " << point_max_.x << endl;
//                cout << "Max y: " << point_max_.y << endl;
//                cout << "Max z: " << point_max_.z << endl;
//                Eigen::Vector4f min_pt = { point_min_.x,point_min_.y,point_min_.z,0 };
//                Eigen::Vector4f max_pt = { point_max_.x,point_max_.y,point_max_.z,0 };
                for (std::size_t i = 0; i < cloud_1->size (); ++i)
                {
                    // Check if the point is inside bounds
                    if (cloud_1->points[i].x < point_min_.x || cloud_1->points[i].y < point_min_.y || cloud_1->points[i].z < point_min_.y)
                        continue;
                    if (cloud_1->points[i].x > point_max_.x || cloud_1->points[i].y > point_max_.y || cloud_1->points[i].z > point_max_.z)
                        continue;
                    cloud_in_box->emplace_back(cloud_1->points[i]);
                }
                cout << "方框内点的个数为:" << cloud_in_box->points.size() << endl;


                std::stringstream ss_1;
                ss_1 << outpath_1 << "//"<< "_block_" << begin + 1 << ".pcd";
                if(cloud_in_box->size() > 0)
                    pcl::io::savePCDFileBinary(ss_1.str(), *cloud_in_box);

                //center distance
                Eigen::Vector4f centroid_seg_, centroid_i_box_;
                PointType centroid_seg_p_, centroid_i_box_p_;
                pcl::compute3DCentroid(*seg_cloud,centroid_seg_);
                pcl::compute3DCentroid(*cloud_in_box,centroid_i_box_);
                centroid_seg_p_.x = centroid_seg_[0];
                centroid_seg_p_.y = centroid_seg_[1];
                centroid_seg_p_.z = centroid_seg_[2];
                centroid_i_box_p_.x = centroid_i_box_[0];
                centroid_i_box_p_.y = centroid_i_box_[1];
                centroid_i_box_p_.z = centroid_i_box_[2];
                float dis_centroid_seg_in_box_ = pcl::euclideanDistance(centroid_seg_p_,centroid_i_box_p_);
                cout << "dis_centroid_seg_in_box_:   " << dis_centroid_seg_in_box_ << endl;
                std::stringstream ss_2;
                ss_2 << outpath_2 << "//"<< "_block_" << begin + 1 << ".pcd";
                if (dis_centroid_seg_in_box_ > 0.1 && cloud_in_box->size() > mean_voxel_size_){
                    pcl::io::savePCDFileBinary(ss_2.str(), *cloud_in_box);
                    cout << begin + 1 << endl;
                }

                     begin++;


            }

            seg_cloud->clear(); // 每分割一次,清空一下容器,进而提高电脑工作效率
        }
    }


    printf("点云体素分块完毕!!!");

    return 0;
}

效果图如下:

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

iPhone 存储不足?快速释放空间的实用技巧

想象一下&#xff0c;您的iPhone上充满了GIF、照片、群聊记录、音乐和游戏。它可能已经成为您存储数据的核心设备&#xff0c;因此很容易就会填满存储空间。尽管iPhone 15和iPhone 14的起始存储容量提升到了128GB&#xff0c;但这对于一些用户来说可能仍然不够用。因此&#xf…

解决国内无法访问huggingface.co

在国内无法访问 https://huggingface.co 时&#xff0c;可以使用国内的镜像站点&#xff1a; HF-Mirror - Huggingface 镜像站加速访问Hugging Face的门户。作为一个公益项目&#xff0c;我们致力于提供稳定、快速的镜像服务&#xff0c;帮助国内用户无障碍访问Hugging Face的…

基于JSP技术的人事管理系统

你好呀&#xff0c;我是计算机学长猫哥&#xff01;如果有相关需求&#xff0c;文末可以找到我的联系方式。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;JSP技术 工具&#xff1a;浏览器&#xff08;如360浏览器、谷歌浏览器、QQ浏览器等&#xff…

史上最走心midjourney教程多案例咒语注意点

一 &#xff1a;什么是Midjourney &#xff1f;&#xff08;文末附 MidJourney 知识库&#xff0c;从注册到使用教程还有高阶技巧应有尽有。&#xff09; Midjourney是一个由同名研究实验室开发的人工智能程式&#xff0c;可根据文本生成图像&#xff0c;于2022年7月12日进入公…

搜维尔科技:【研究】Xsens Link对跑步运动学的可靠性

内容类型&#xff1a;客户案例 产品&#xff1a;MVN Link 产品用例&#xff1a;教育科研 应用领域&#xff1a;运动分析 在实验室环境之外分析现实环境中人体运动的能力正变得越来越重要。各个学科的研究人员&#xff0c;尤其是运动科学和生物力学的研究人员&a…

【Mongodb】Mongodb亿级数据性能测试和压测

一&#xff0c;mongodb数据性能测试 如需转载&#xff0c;请标明出处&#xff1a;https://zhenghuisheng.blog.csdn.net/article/details/139505973 mongodb数据性能测试 一&#xff0c;mongodb数据性能测试1&#xff0c;mongodb数据库创建和索引设置2&#xff0c;线程池批量…

C语言二级指针、指针数组

一、二级指针 指针变量也是变量&#xff0c;是变量就应有地址&#xff0c;那指针变量的地址存放在哪里&#xff1f;存放在二级指针变量。 此时&#xff0c;*ppa pa&#xff0c;**ppa a。 二、指针数组 指针数组&#xff0c;顾名思义就是存放指针的数组。 数组每个元素为int类…

精准导航:用A*算法优化栅格地图的路径规划【附Matlab代码】

目录 1.算法原理2.代码讲解3.结果展示4.代码获取 1.算法原理 A* 算法是一种基于传统图搜索的智能启发式算法&#xff0c;它具有稳定性高、节点搜索效率高等优点。主要原理为&#xff1a;以起点作为初始节点&#xff0c;搜索初始节点旁 8 个邻域&#xff0c;并通过启发函数评估…

IGraph使用实例——线性代数计算(blas)

1 概述 在图论中&#xff0c;BLAS&#xff08;Basic Linear Algebra Subprograms&#xff09;并不直接应用于图论的计算&#xff0c;而是作为一套线性代数计算中通用的基本运算操作函数集合&#xff0c;用于进行向量和矩阵的基本运算。然而&#xff0c;这些基本运算在图论的相…

深度神经网络——什么是扩散模型?

1. 概述 在人工智能的浩瀚领域中&#xff0c;扩散模型正成为技术创新的先锋&#xff0c;它们彻底改变了我们处理复杂问题的方式&#xff0c;特别是在生成式人工智能方面。这些模型基于高斯过程、方差分析、微分方程和序列生成等坚实的数学理论构建。 业界巨头如Nvidia、Google…

STM32(七):ADC电位检测 (标准库函数)

前言 上一篇文章已经介绍了如何用STM32单片机中的定时器的PWM波来实现LED的“呼吸”。这篇文章我们来介绍一下如何用STM32单片机中ADC进行电位检测&#xff0c;并发送到XCOM串口中显示。 一、实验原理 1.ADC模数转换的介绍 首先&#xff0c;我们先介绍一下AD模数模块&#…

驱动开发:内核扫描SSDT挂钩状态

100编程书屋_孔夫子旧书网 在笔者上一篇文章《驱动开发:内核实现SSDT挂钩与摘钩》中介绍了如何对SSDT函数进行Hook挂钩与摘钩的,本章将继续实现一个新功能,如何检测SSDT函数是否挂钩,要实现检测挂钩状态有两种方式,第一种方式则是类似于《驱动开发:摘除InlineHook内核钩…

免费,C++蓝桥杯等级考试真题--第11级(含答案解析和代码)

C蓝桥杯等级考试真题--第11级 答案&#xff1a;D 解析&#xff1a; A. a b; b a; 这种方式会导致a和b最终都等于b原来的值&#xff0c;因为a的原始值在被b覆盖前没有保存。 B. swap(a&#xff0c;b); 如果没有自定义swap函数或者没有包含相应的库&#xff0c;这个选项会编…

Mysql执行一条语句都有哪些操作

Mysql的执行流程 MySQL 的架构共分为两层&#xff1a;Server 层和存储引擎层&#xff0c; Server 层负责建立连接、分析和执行 SQL。MySQL 大多数的核心功能模块都在这实现&#xff0c;主要包括连接器&#xff0c;查询缓存、解析器、预处理器、优化器、执行器等。另外&#xf…

Linux——PXE_FTP_EL8

PXE Kickstart &#xff08; el8 &#xff09; 使用两个网口一个用net接口用于下载服务和软件包&#xff0c;另一个为仅主机用于与其他的空主机相连 PXE(preboot execute environment) 预启动执行环境。支持工作站通过网络从远端服务器下载映像&#xff0c;并由此支持通过网络启…

JavaWeb2-Vue

Vue 前端框架&#xff0c;免除原生JS中的DOM操作简化书写 &#xff08;以前学过又忘了&#xff0c;现在才知道原来vue是前端的&#xff09; 基于MVVM思想&#xff08;model-view -viewModel&#xff09;实现数据双向绑定 model是数据模型 view负责数据展示 即DOM 中间这个负责…

可视化表单生成器好用吗?

当前的社会竞争是非常大的&#xff0c;随着业务的上涨&#xff0c;很多客户都需要找到更高效、更理想的软件平台产品实现流程化办公。这就需要了解低代码技术平台了。作为新的办公助力软件平台&#xff0c;低代码技术平台更好操作、更灵活、功能更多&#xff0c;其中可视化表单…

生产管理看板系统为优化工厂车间生产工艺

一、行业现状&#xff0c;管理中普遍存在的问题 1. 先进的管理流程与相应管理制度匮乏。大量管理工作依旧主要采取“人治”模式&#xff0c;众多高层自身理论知识欠缺&#xff0c;并且还难以听取相关人员的意见。 2. 生产过程的控制较为薄弱。企业全面质量控制&#xff08;TQ…

LSP5526 直接替用 LSP5502 SOP-8降压直流转换器

LSP5526 作为一款高性能的降压型直流-直流转换器&#xff0c;在医疗设备中的应用非常广泛。由于其具有高效率、宽输入电压范围以及良好的稳定性等特点&#xff0c;它可以为医疗设备中的关键电子系统提供稳定的电源支持。以下是一些具体的医疗设备应用案例&#xff1a; 1. 医用监…

人大金仓数据库报sys_user表字段不存在的问题

目录 一.问题&#xff1a; 二.原因 三.解决方法&#xff1a; 一.问题&#xff1a; 公司的一个项目从oracle切换到人大金仓之后&#xff0c;突然报了一个sys_user里面的字段不存在。 二.原因 检查了很多次确信sys_user表没问题&#xff0c;查了相应的文档之后发现原来人大金…