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

PCL 计算点云的投影密度

目录

  • 一、算法原理
    • 1. 点云投影
    • 2. 网格划分
    • 3. 密度计算
    • 4. 完整流程
    • 5. 关键公式说明
  • 二、代码实现
  • 三、结果展示

在这里插入图片描述

博客长期更新,本文最新更新时间为:2025年6月14日。

一、算法原理

1. 点云投影

   设原始点云集合为:
P = { p i } i = 1 N , p i = ( x i , y i , z i ) ∈ R 3 P = \{ \mathbf{p}_i \}_{i=1}^N, \quad \mathbf{p}_i = (x_i, y_i, z_i) \in \mathbb{R}^3 P={pi}i=1N,pi=(xi,yi,zi)R3

投影到XY平面(可推广到任意平面):
P proj = { ( x i , y i ) } i = 1 N P_{\text{proj}} = \{ (x_i, y_i) \}_{i=1}^N Pproj={(xi,yi)}i=1N

2. 网格划分

计算投影点集边界:
{ x min ⁡ = min ⁡ 1 ≤ i ≤ N x i x max ⁡ = max ⁡ 1 ≤ i ≤ N x i y min ⁡ = min ⁡ 1 ≤ i ≤ N y i y max ⁡ = max ⁡ 1 ≤ i ≤ N y i \begin{cases} x_{\min} = \min\limits_{1 \leq i \leq N} x_i \\ x_{\max} = \max\limits_{1 \leq i \leq N} x_i \\ y_{\min} = \min\limits_{1 \leq i \leq N} y_i \\ y_{\max} = \max\limits_{1 \leq i \leq N} y_i \end{cases} xmin=1iNminxixmax=1iNmaxxiymin=1iNminyiymax=1iNmaxyi

定义网格尺寸 s s s(用户参数),计算网格维度:
m = ⌈ x max ⁡ − x min ⁡ s ⌉ , n = ⌈ y max ⁡ − y min ⁡ s ⌉ m = \left\lceil \frac{x_{\max} - x_{\min}}{s} \right\rceil, \quad n = \left\lceil \frac{y_{\max} - y_{\min}}{s} \right\rceil m=sxmaxxmin,n=symaxymin

3. 密度计算

对于网格单元 ( j , k ) (j,k) (j,k)

  • 区域范围 R j k = [ x min ⁡ + j ⋅ s , x min ⁡ + ( j + 1 ) ⋅ s ) × [ y min ⁡ + k ⋅ s , y min ⁡ + ( k + 1 ) ⋅ s ) R_{jk} = [x_{\min} + j \cdot s, x_{\min} + (j+1) \cdot s) \times [y_{\min} + k \cdot s, y_{\min} + (k+1) \cdot s) Rjk=[xmin+js,xmin+(j+1)s)×[ymin+ks,ymin+(k+1)s)
  • 点数统计
    C j k = ∑ i = 1 N 1 R j k ( x i , y i ) C_{jk} = \sum_{i=1}^{N} \mathbf{1}_{R_{jk}}(x_i, y_i) Cjk=i=1N1Rjk(xi,yi)
    其中 1 \mathbf{1} 1 为指示函数:
    1 R j k ( x , y ) = { 1 if  ( x , y ) ∈ R j k 0 otherwise \mathbf{1}_{R_{jk}}(x,y) = \begin{cases} 1 & \text{if } (x,y) \in R_{jk} \\ 0 & \text{otherwise} \end{cases} 1Rjk(x,y)={10if (x,y)Rjkotherwise
  • 点密度
    D j k = C j k A , A = s 2 ( 单位面积 ) D_{jk} = \frac{C_{jk}}{A}, \quad A = s^2 \quad (\text{单位面积}) Djk=ACjk,A=s2(单位面积)

4. 完整流程

输入:点云  P , 网格尺寸  s ↓ 1. 投影: P proj = { ( x i , y i ) ∣ ∀ p i ∈ P } ↓ 2. 边界计算: x min ⁡ , x max ⁡ , y min ⁡ , y max ⁡ ↓ 3. 网格划分: m × n 网格 ↓ 4. 密度计算: D j k = 1 s 2 ∑ i = 1 N 1 [ x min ⁡ + j s , x min ⁡ + ( j + 1 ) s ) ( x i ) ⋅ 1 [ y min ⁡ + k s , y min ⁡ + ( k + 1 ) s ) ( y i ) for  j = 0 , … , m − 1 ; k = 0 , … , n − 1 ↓ 输出:密度矩阵  D = [ D j k ] m × n \boxed{ \begin{array}{c} \text{输入:点云 } P, \text{ 网格尺寸 } s \\ \downarrow \\ \text{1. 投影:} P_{\text{proj}} = \{(x_i,y_i) | \forall \mathbf{p}_i \in P\} \\ \downarrow \\ \text{2. 边界计算:} x_{\min}, x_{\max}, y_{\min}, y_{\max} \\ \downarrow \\ \text{3. 网格划分:} m \times n \text{ 网格} \\ \downarrow \\ \text{4. 密度计算:} \\ D_{jk} = \dfrac{1}{s^2} \sum\limits_{i=1}^{N} \mathbf{1}_{[x_{\min}+js,\ x_{\min}+(j+1)s)}(x_i) \cdot \mathbf{1}_{[y_{\min}+ks,\ y_{\min}+(k+1)s)}(y_i) \\ \text{for } j=0,\dots,m-1; \ k=0,\dots,n-1 \\ \downarrow \\ \text{输出:密度矩阵 } \mathbf{D} = [D_{jk}]_{m \times n} \end{array} } 输入:点云 P, 网格尺寸 s1. 投影:Pproj={(xi,yi)∣∀piP}2. 边界计算:xmin,xmax,ymin,ymax3. 网格划分:m×n 网格4. 密度计算:Djk=s21i=1N1[xmin+js, xmin+(j+1)s)(xi)1[ymin+ks, ymin+(k+1)s)(yi)for j=0,,m1; k=0,,n1输出:密度矩阵 D=[Djk]m×n

5. 关键公式说明

  1. 网格索引映射
    j = ⌊ x i − x min ⁡ s ⌋ , k = ⌊ y i − y min ⁡ s ⌋ j = \left\lfloor \frac{x_i - x_{\min}}{s} \right\rfloor, \quad k = \left\lfloor \frac{y_i - y_{\min}}{s} \right\rfloor j=sxixmin,k=syiymin
    确保点落入正确网格单元

  2. 边界处理
    j ∈ [ 0 , m − 1 ] , k ∈ [ 0 , n − 1 ] j \in [0, m-1], \quad k \in [0, n-1] j[0,m1],k[0,n1]
    超出范围的索引被丢弃

  3. 密度单位
    D j k D_{jk} Djk 单位为 点 / m 2 \text{点}/\text{m}^2 /m2(当 s s s 以米为单位时),用于量化局部点云密度

此方法通过降维投影和空间离散化,将三维密度计算转化为二维直方图统计,是点云分析的基础操作。

二、代码实现

#include <vector>
#include <pcl/io/pcd_io.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/common/common.h>// 计算投影密度
void computeProjectionDensity(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud, float grid_size, std::vector<std::vector<float>>& density_grid)
{// 获取点云边界pcl::PointXYZ min_pt, max_pt;pcl::getMinMax3D(*cloud, min_pt, max_pt);// 计算网格维度(XY平面投影)int grid_x = ceil((max_pt.x - min_pt.x) / grid_size);int grid_y = ceil((max_pt.y - min_pt.y) / grid_size);// 初始化密度网格density_grid.resize(grid_x, std::vector<float>(grid_y, 0.0f));// 统计每个网格的点数for (const auto& point : cloud->points) {int x_idx = (point.x - min_pt.x) / grid_size;int y_idx = (point.y - min_pt.y) / grid_size;if (x_idx >= 0 && x_idx < grid_x && y_idx >= 0 && y_idx < grid_y) {density_grid[x_idx][y_idx] += 1.0f;}}// 计算密度(点数/单位面积)float cell_area = grid_size * grid_size;for (int i = 0; i < grid_x; ++i) {for (int j = 0; j < grid_y; ++j) {density_grid[i][j] /= cell_area;}}
}// 使用示例
int main() 
{pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);if (pcl::io::loadPCDFile<pcl::PointXYZ>("E://data//道路.pcd", *cloud) == -1){PCL_ERROR("Cloudn't read file!");return -1;}std::vector<std::vector<float>> density_grid;computeProjectionDensity(cloud, 0.1f, density_grid); // 网格尺寸0.1m// 输出密度结果for (const auto& row : density_grid) {for (float density : row) {std::cout << density << " ";}std::cout << std::endl;}return 0;
}

三、结果展示

在这里插入图片描述

http://www.xdnf.cn/news/1042543.html

相关文章:

  • 【整数递增加法拆分】2022-4-11
  • LangGraph基础知识(Human-in-the-loop)(五)
  • 《甘肃棒垒球》奥运会项目有哪些·垒球1号位
  • vue | async-validator 表单验证库 第三方库安装与使用
  • 高效I/O处理:模型与多路复用的探讨
  • Spring学习笔记
  • (14)python+ selenium自动化测试 -回顾
  • 探索数据的力量:Elasticsearch中指定链表字段的统计查询记录
  • 生日悖论理论及在哈希函数碰撞中的应用
  • AI视野:写作应用AI排行榜Top10 | 2025年05月
  • 隐式时钟与外时钟对比2025.6.14
  • boost之signal的封装及使用例子
  • 数列求和计算
  • XCTF-misc-János-the-Ripper
  • C++斯特林数在C++中的数学理论与计算实现1
  • 飞牛NAS本地化部署Dify打造私有LLMOps平台
  • CARSIM-制动压力与制动踏板行程关系
  • acm模式stringstream
  • 滚珠螺杆的预紧间隙如何调整?
  • 大模型量化与剪枝
  • 无监督的预训练和有监督任务的微调
  • 源端串联端接
  • 【八股消消乐】构建微服务架构体系—实现制作库与线上库分离
  • 图的遍历模板
  • Linux【8】-----Linux系统编程(并发编程原理与应用)
  • YOLO系列对指定图片绘制模型热力图
  • Day.31
  • 从0到1开发一个自己的工具 MCP 并发布到 test PyPi(Python个人版)
  • 代码审计服务:如何解决误报与漏报难题,保障软件安全?
  • 从MVC到MVVM:从过程式走向声明式