当前位置: 首页 > article >正文

PCL点云按指定方向进行聚类(指定类的宽度)

 

需指定方向和类的宽度。测试代码如下:

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/segmentation/extract_clusters.h>
#include <pcl/common/centroid.h>  // 新增质心计算头文件
#include <pcl/common/common.h> //类型定义简化
typedef pcl::PointXYZ PointT;
typedef pcl::PointCloud<PointT> PointCloudT;/*** @brief 沿Z轴方向聚类点云,限制每类在Z轴的长度不超过thresh* @param cloud 输入点云* @param thresh Z轴方向的最大允许长度* @return 聚类结果的索引集合*/
std::vector<pcl::PointIndices> axisAlignedClustering(Eigen::Vector3f direction,const PointCloudT::Ptr& cloud, float thresh)
{std::vector<pcl::PointIndices> clusters;if (cloud->empty()) return clusters;auto p0 = cloud->points[0];direction.normalize();
auto project_dist = [&direction, &p0](PointT& p){return direction.dot(Eigen::Vector3f(p.x - p0.x, p.y - p0.y, p.z - p0.z));};std::vector<int> indices(cloud->size());for (int i = 0; i < indices.size(); ++i) indices[i] = i;std::sort(indices.begin(), indices.end(), [&](int a, int b) {return project_dist(cloud->points[a]) < project_dist(cloud->points[b]);});//2. 滑动窗口分割pcl::PointIndices current_cluster;float start_z = project_dist(cloud->points[indices[0]]);//cloud->points[indices[0]].z;current_cluster.indices.push_back(indices[0]);for (size_t i = 1; i < indices.size(); ++i) {float current_z = project_dist(cloud->points[indices[i]]);if (current_z - start_z <= thresh) {current_cluster.indices.push_back(indices[i]);}else {clusters.push_back(current_cluster);current_cluster.indices.clear();current_cluster.indices.push_back(indices[i]);start_z = current_z;}}if (!current_cluster.indices.empty()) {clusters.push_back(current_cluster);}return clusters;
}/*** @brief 可视化聚类结果* @param cloud 原始点云* @param clusters 聚类索引*/
void visualizeClusters(const PointCloudT::Ptr& cloud,const std::vector<pcl::PointIndices>& clusters, float cloud_size, Eigen::Vector4f centroid)
{pcl::visualization::PCLVisualizer viewer("Cluster Visualization");viewer.setBackgroundColor(0, 0, 0);	//为每个聚类生成随机颜色std::vector<pcl::visualization::PointCloudColorHandlerCustom<PointT>> color_handlers;for (size_t i = 0; i < clusters.size(); ++i) {uint8_t r = rand() % 256;uint8_t g = rand() % 256;uint8_t b = rand() % 256;color_handlers.emplace_back(pcl::visualization::PointCloudColorHandlerCustom<PointT>(cloud, r, g, b));}//添加每个聚类的点云到可视化for (size_t i = 0; i < clusters.size(); ++i) {PointCloudT::Ptr cluster_cloud(new PointCloudT);pcl::ExtractIndices<PointT> extract;pcl::PointIndices::Ptr indices(new pcl::PointIndices(clusters[i]));extract.setInputCloud(cloud);extract.setIndices(indices);extract.filter(*cluster_cloud);std::string cluster_id = "cluster_" + std::to_string(i);viewer.addPointCloud<PointT>(cluster_cloud, color_handlers[i], cluster_id);viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, cluster_id);}// 关键参数设置const float camera_distance = 3.0 * cloud_size;  // 观察距离为点云尺寸的3倍const Eigen::Vector3f camera_pos = {centroid[0],centroid[1],centroid[2] + camera_distance};
viewer.initCameraParameters();
viewer.setCameraPosition(camera_pos[0], camera_pos[1], camera_pos[2],  // 相机位置centroid[0], centroid[1], centroid[2],         // 焦点位置0, -1, 0                                       // 上方向向量(Y轴负方向)
);viewer.addCoordinateSystem(1.0);while (!viewer.wasStopped()) {viewer.spinOnce(100);}
}int main(int argc, char** argv) {//1. 创建点云对象
pcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>);//2. 打开并读取TXT文件
std::ifstream file("E:\\Data\\PathPlanning\\data.txt");
if (!file.is_open()) {std::cerr << "Error opening file: " << argv[1] << std::endl;return -1;
}std::string line;
while (std::getline(file, line)) {if (line.empty()) continue;std::istringstream iss(line);PointT point;//读取坐标 (x,y,z) 和法向量float nx, ny, nz;if (!(iss >> point.x >> point.y >> point.z >> nx >> ny >> nz)) {std::cerr << "Error parsing line: " << line << std::endl;continue;}cloud->push_back(point);
}
file.close();//3. 设置点云属性
cloud->width = cloud->size();
cloud->height = 1;
cloud->is_dense = false;// 计算点云质心
Eigen::Vector4f centroid;
if (pcl::compute3DCentroid(*cloud, centroid)){std::cout << "点云质心坐标: ("<< centroid[0] << ", "<< centroid[1] << ", "<< centroid[2] << ")" << std::endl;
}
else {std::cerr << "无法计算空点云的质心" << std::endl;return -1;
}// 计算点云尺寸范围
PointT min_pt, max_pt;
pcl::getMinMax3D(*cloud, min_pt, max_pt);
float cloud_size = std::max({max_pt.x - min_pt.x,max_pt.y - min_pt.y,max_pt.z - min_pt.z});//2. 沿Z轴聚类(设置Thresh = 1.0)
float thresh = 100.0f;
std::vector<pcl::PointIndices> clusters = axisAlignedClustering(Eigen::Vector3f(1, 1, 0), cloud, thresh);//3. 输出聚类信息
std::cout << "Found " << clusters.size() << " clusters." << std::endl;
for (size_t i = 0; i < clusters.size(); ++i) {std::cout << "Cluster " << i << ": " << clusters[i].indices.size()<< " points" << std::endl;
}//4. 可视化
visualizeClusters(cloud, clusters, cloud_size, centroid);	return 0;
}

相关文章:

PCL点云按指定方向进行聚类(指定类的宽度)

需指定方向和类的宽度。测试代码如下&#xff1a; #include <iostream> #include <fstream> #include <vector> #include <string> #include <pcl/point_types.h> #include <pcl/point_cloud.h> #include <pcl/visualization/pcl_visu…...

复现nn-Unet模型 实验报告

目的是将 nn-Unet 模型应用到切割脑出血CT图像上 论文学习步骤为 1.学习Unet&#xff0c;Unet等模型作为复现nn-Unet模型的基础。 2.学习nn-Unet原论文&#xff0c;掌握nn-Unet的结构。 3.学习将nn-Unet模型应用到切割脑出血CT医学图像的相关论文。 这周学习了Unet&#x…...

C#对SQLServer增删改查

1.创建数据库 2.SqlServerHelper using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Data; using System.Linq; using System.Text; using System.Threading.Tasks;namespace WindowsFormsApp1 {internal class SqlServerHelper{//…...

模拟太阳系(C#编写的maui跨平台项目源码)

源码下载地址&#xff1a;https://download.csdn.net/download/wgxds/90789056 本资源为用C#编写的maui跨平台项目源码&#xff0c;使用Visual Studio 2022开发环境&#xff0c;基于.net8.0框架&#xff0c;生成的程序为“模拟太阳系运行”。经测试&#xff0c;生成的程序可运行…...

蓝桥杯14届 数三角

问题描述 小明在二维坐标系中放置了 n 个点&#xff0c;他想在其中选出一个包含三个点的子集&#xff0c;这三个点能组成三角形。然而这样的方案太多了&#xff0c;他决定只选择那些可以组成等腰三角形的方案。请帮他计算出一共有多少种选法可以组成等腰三角形&#xff1f; 输…...

redis sentinel和redis cluster的主从切换选举过程

引言 redis sentinel和redis cluster的主从切换选举过程不同&#xff0c;本文将从选举机制、核心差异对比两者的不同。 一、Redis Sentinel的选举机制 监控与故障判定 Sentinel集群通过心跳检测&#xff08;每秒一次PING&#xff09;监控主节点状态&#xff1a; 主观下线&…...

C++自学笔记 makefile

本博客参考南科大于仕琪教授的讲解视频和这位同学的学习笔记&#xff1a; 参考博客 感谢两位的分享。 makefile 的作用 用于组织大型项目的编译&#xff0c;是一个一键编译项目的脚本文件。 本博客通过四个版本的makefile逐步说明makefile的使用 使用说明 四个演示文件 …...

前端密码加密:保护用户数据的第一道防线

引言 在当今互联网时代&#xff0c;用户数据安全至关重要&#xff0c;而密码作为用户身份验证的核心凭证&#xff0c;其安全性更是重中之重。传统的前端开发中&#xff0c;密码常常以明文形式传输到服务器&#xff0c;这带来了严重的安全隐患。本文将深入探讨前端密码加密的必…...

HTML12:文本框和单选框

表单元素格式 属性说明type指定元素的类型。text、password、 checkbox、 radio、submit、reset、file、hidden、image 和button&#xff0c;默认为textname指定表单元素的名称value元素的初始值。type为radio时必须指定一个值size指定表单元素的初始宽度。当type为text 或pas…...

机器人厨师上岗!AI在餐饮界掀起新风潮!

想要了解人工智能在其他各个领域的应用&#xff0c;可以查看下面一篇文章 《AI在各领域的应用》 餐饮业是与我们日常生活息息相关的行业&#xff0c;而人工智能&#xff08;AI&#xff09;正在迅速改变这个传统行业的面貌。从智能点餐到食材管理&#xff0c;再到个性化推荐&a…...

MySQL开篇

文章目录 一、前置知识1. MySQL的安装2. 前置一些概念知识 二、MySQL数据库操作2.1 概念2.2 数据库的操作2.2.1创建数据库命令2.2.2 查看数据库2.2.3 选中数据库2.2.4 删除数据库 三、MySQL数据表操作3.1 概念3.2 数据表的操作3.2.1 创建表 一、前置知识 1. MySQL的安装 MySQ…...

Linux电脑本机使用小皮面板集成环境开发调试WEB项目

开发调试WEB项目&#xff0c;有时开发环境配置繁琐&#xff0c;可以使用小皮面板集成环境。 小皮面板官网&#xff1a; https://www.xp.cn/1.可以使用小皮面板安装脚本一键安装。登陆小皮面板管理后台 2.在“软件商店”使用LNMP一键部署集成环境。 3.添加网站&#xff0c;本…...

问题及解决01-面板无法随着窗口的放大而放大

在MATLAB的App Designer中&#xff0c;默认情况下&#xff0c;组件的位置是固定的&#xff0c;不会随着父容器的大小变化而改变。问题图如下图所示。 解决&#xff1a; 为了让Panel面板能够随着UIFigure父容器一起缩放&#xff0c;需要使用布局管理器&#xff0c;我利用 MATLA…...

操作系统原理实验报告

操作系统原理课程的实验报告汇总 实验三&#xff1a;线程的创建与撤销 实验环境&#xff1a;计算机一台&#xff0c;内装有VC、office等软件 实验日期&#xff1a;2024.4.11 实验要求&#xff1a; 1.理解&#xff1a;Windows系统调用的基本概念&#xff0c;进程与线程的基…...

《Linux命令行大全(第2版)》PDF下载

内容简介 本书对Linux命令行进行详细的介绍&#xff0c;全书内容包括4个部分&#xff0c;第一部分由Shell的介绍开启命令行基础知识的学习之旅&#xff1b;第二部分讲述配置文件的编辑&#xff0c;如何通过命令行控制计算机&#xff1b;第三部分探讨常见的任务与必备工具&…...

Java高频面试之并发编程-15

hello啊&#xff0c;各位观众姥爷们&#xff01;&#xff01;&#xff01;本baby今天又来报道了&#xff01;哈哈哈哈哈嗝&#x1f436; 面试官&#xff1a;as-if-serial 是什么&#xff1f;单线程的程序一定是顺序执行的吗&#xff1f; as-if-serial 规则 定义&#xff1a; …...

Python-86:奇妙货币交易问题

问题描述 小R住在一个名为 X 国的国家&#xff0c;这里的货币非常特殊&#xff0c;面值为 V0,V1,V2,...,VnV0,V1,V2,...,Vn&#xff0c;并且 nn 可以无限大。该国的交易规则也很特别&#xff1a;在一次交易中&#xff0c;双方只能对每种面值的货币使用不超过两次。 例如&…...

Selenium的driver.get_url 和 手动输入网址, 并点击的操作,有什么不同?

我在搞爬取的时候&#xff0c;发现有些网站直接用driver.get(url) 跳转到目标特定的网址的时候&#xff0c;会被强制跳转到其他的网址上&#xff0c;但是如果是自己手动&#xff0c;在网址栏那里输入网址&#xff0c;并点回车&#xff0c;却能完成跳转。 这是在使用 Selenium …...

kotlin @JvmStatic注解的作用和使用场景

1. JvmStatic 的作用 JvmStatic 是 Kotlin 提供的一个注解&#xff0c;用于在 JVM 上将伴生对象&#xff08;companion object&#xff09;中的方法或属性暴露为 Java 静态方法或字段。 作用对象&#xff1a;只能用在 companion object 中的函数或属性。效果&#xff1a; 在 …...

GitHub中多个PR时,如何协同合并和管理

在 GitHub 中&#xff0c;当多个开发者同时提交多个 Pull Request&#xff08;PR&#xff09;时&#xff0c;合理的管理流程与协作策略能够确保代码库稳定、审查高效&#xff0c;并减少冲突与重工。总体而言&#xff0c;你需要&#xff1a; 1&#xff09;统一分支与命名策略&a…...

无人甘蔗小车履带式底盘行走系统的研究

1.1 研究背景与意义 1.1.1 研究背景 甘蔗作为全球最重要的糖料作物之一&#xff0c;在农业经济领域占据着举足轻重的地位。我国是甘蔗的主要种植国家&#xff0c;尤其是广西、广东、云南等地&#xff0c;甘蔗种植面积广泛&#xff0c;是当地农业经济的重要支柱产业。甘蔗不仅…...

通俗易懂版知识点:Keepalived + LVS + Web + NFS 高可用集群到底是干什么的?

实验开始前&#xff0c;先搞懂为什么要部署该集群&#xff1f; 这个方案的目标是让网站 永不宕机&#xff0c;即使某台服务器挂了&#xff0c;用户也感觉不到。它主要涉及 负载均衡&#xff08;LVS&#xff09; 高可用&#xff08;Keepalived&#xff09; 共享存储&#xff…...

各类有关NBA数据统计数据集大合集

这些数据我已上传大家在CSDN上直接搜索就可以&#xff01; 一、【2022-2023 NBA球员统计】数据集 关键词: 篮球 描述: 语境 该数据集每场比赛包含2022-2023常规赛NBA球员统计数据。 请注意&#xff0c;由团队更改产生了重复的球员名称。 * [2021-2022 NBA播放器统计]&#…...

《社交应用架构生存战:React Native与Flutter的部署容灾决胜法则》

React Native和Flutter作为当下热门的跨平台开发框架&#xff0c;在社交应用开发领域各显神通。今天&#xff0c;我们深入探索它们在高可用架构中的部署与容灾策略。 React Native凭借其独特优势&#xff0c;在社交应用开发中拥有一席之地。它基于JavaScript和React&#xff0…...

https,http1,http2,http3的一些知识

温故知新&#xff0c;突然有人问我项目中&#x1f914;有使用http3么&#xff0c;一下不知从何说起&#xff0c;就有了这篇文章的出现。 https加密传输&#xff0c;ssltls https 验证身份 提供加密&#xff0c;混合加密 &#xff1a; 对称加密 非对称加密 原理&#xff1a…...

go 通过汇编学习atomic原子操作原理

文章目录 概要一、原理1.1、案例1.2、关键汇编 二、LOCK汇编指令2.1、 LOCK2.2、 原理2.2.1、 缓存行2.2.2、 缓存一致性之MESI协议2.2.3、lock原理 三、x86缓存发展四、x86 DMA发展参考 概要 在并发操作下&#xff0c;对一个简单的aa2的操作都会出错&#xff0c;这是因为这样…...

WebRTC 源码原生端Demo入门-1

1、概述 我的代码是比较新的&#xff0c;基于webrtc源码仓库的main分支的&#xff0c;在windows下把源码仓库下载好了后&#xff0c;用visual stdio 2022打开进行编译调试src/examples/peerconnection_client测试项目,主要是跑通这个demo来入手和调试&#xff0c;纯看代码很难…...

Nipype 简单使用教程

Nipype 简单使用教程 基础教程**一、Nipype 核心概念与工作流构建****1. 基本组件****2. 工作流构建步骤** **二、常用接口命令速查表****1. FSL 接口****2. FreeSurfer 接口****3. ANTS 接口****4. 数据处理接口** **三、高级特性与最佳实践****1. 条件执行&#xff08;基于输…...

股票回购、股票减持和股票解禁对股票价格影响的综合分析

以下是关于股票回购、股票减持和股票解禁对股票价格影响的综合分析&#xff0c;结合了市场机制、财务指标及投资者行为等多维度因素&#xff1a; 一、股票回购对股价的影响 1. 正面影响 • 提升财务指标&#xff1a;回购减少流通股数量&#xff0c;在净利润不变的情况下&#…...

linux 三剑客命令学习

grep Grep 是一个命令行工具&#xff0c;用于在文本文件中搜索打印匹配指定模式的行。它的名称来自于 “Global Regular Expression Print”&#xff08;全局正则表达式打印&#xff09;&#xff0c;它最初是由 Unix 系统上的一种工具实现的。Grep 工具在 Linux 和其他类 Unix…...