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

【编程实践】点云曲率计算与可视化

基于Open3D和kNN的点云曲率计算与可视化,按下面指标定义的曲率

输入数据

  • 输入数据
    点云文件ply或pcd,加载为点云对象

指标定义

  • 此处曲率定义:采用基于点云PCA协方差分析的局部曲率估计方法。对于每个点,其曲率定义为:
    κ=λ1λ1+λ2+λ3\kappa = \frac{\lambda_{1}}{\lambda_{1}+\lambda_{2}+\lambda_{3}}κ=λ1+λ2+λ3λ1
    其中λ1\lambda_{1}λ1是协方差矩阵最小特征值,反映法向方向上的变化程度。该指标不具备严格几何意义的主曲率属性,但在点云中广泛应用于反映局部几何尖锐程度和表面变化趋势。

数学处理过程

  1. 邻域搜索(K-Nearest Neighbour)
  • 对每个点pip_{i}pi
    • 使用KD树查找其最近的k个临近点,点本身也被包含在邻域中;
    • 得到临近点集N(pi)={pi1,pi2,...,pik}\mathscr{N}(p_i)=\{p_{i1},p_{i2},...,p_{ik}\}N(pi)={pi1,pi2,...,pik} ,对于某个点pip_{i}pi有k个邻接点。
  1. 协方差矩阵计算
    对于每个邻域点集N(pi)\mathscr{N}(p_i)N(pi),计算其三维坐标协方差矩阵:
    Ci=Cov(N(pi))∈R3×3C_i = Cov(\mathscr{N}(p_i)) \in \mathbb{R^{3 \times 3}} Ci=Cov(N(pi))R3×3
    即:
    Ci=1k∑j=1k(pij−p‾i)(pij−p‾i)TC_i = \frac{1}{k}\sum^{k}_{j=1}(p_{ij}-\overline{p}_{i})(p_{ij}-\overline{p}_{i})^{T}Ci=k1j=1k(pijpi)(pijpi)T
    其中,p‾i\overline{p}_{i}pi是邻域点的均值向量。

  2. 特征值分级(Eigen Decomposition)
    计算协方差矩阵的特征值λ1\lambda_{1}λ1λ2\lambda_{2}λ2λ3\lambda_{3}λ3并排序:
    λ1≤λ2≤λ3\lambda_{1} \leq \lambda_{2} \leq \lambda_{3}λ1λ2λ3
    特征值代表该邻域点云在主轴方向上的分布方差。
    注:此处写的是数学上的标准形式1/k,属于有偏估计;实际适用了numpy的无偏估计1/(k-1).

  3. 曲率估计
    使用下面公式估算每个点的局部曲率:
    κi=λ1∑(λi)+ϵ\kappa_{i} = \frac{\lambda_{1}}{\sum(\lambda_{i})+ \epsilon}κi=(λi)+ϵλ1
    其中,λ1\lambda_{1}λ1为最小特征值,表示法向方向上的变化;分母为总变化量,归一化;ϵ\epsilonϵ为防止分母为0加的小常数。

曲率可视化(颜色映射)

  • 对所有点的曲率值κi\kappa_{i}κi进行归一化:
    κinorm=κi−min⁡(κ)max⁡(κ)−min⁡(κ)+ϵ\kappa^{\text{norm}}_{i} = \frac{\kappa_{i}-\min(\kappa)}{\max{(\kappa)}-\min{(\kappa)}+\epsilon}κinorm=max(κ)min(κ)+ϵκimin(κ)
  • 将归一化值使用Matplotlib的 jet 颜色映射为RGB颜色:
    colori=jet(κinorm)\text{color}_{i} = jet(\kappa^{\text{norm}}_{i})colori=jet(κinorm)
  • 将颜色赋值回Open3D点云对象用于可视化。

import open3d as o3d
import numpy as np
import matplotlib.pyplot as plt# 加载点云
pcd = o3d.io.read_point_cloud("Result.ply")
# 构建KD树
pcd_tree = o3d.geometry.KDTreeFlann(pcd)
# ---- 曲率计算函数(基于kNN) ----
def compute_curvature(pcd, knn=30):points = np.asarray(pcd.points)curvatures = []for i in range(len(points)):_, idx, _ = pcd_tree.search_knn_vector_3d(points[i], knn)neighbors = points[idx]covariance = np.cov(neighbors.T)eigvals, _ = np.linalg.eigh(covariance)eigvals = np.sort(eigvals)curvature = eigvals[0] / (np.sum(eigvals) + 1e-10)  # 避免除0curvatures.append(curvature)return np.array(curvatures)
# ---- 计算曲率 ----
curvatures = compute_curvature(pcd, knn=20)
# ---- 映射为颜色(使用matplotlib colormap) ----
norm_curvatures = (curvatures - np.min(curvatures)) / (np.max(curvatures) - np.min(curvatures) + 1e-10)
colors = plt.cm.jet(norm_curvatures)[:, :3]  # 只取 RGB,不要 alpha
pcd.colors = o3d.utility.Vector3dVector(colors)
# ---- 可视化 ----
o3d.visualization.draw_geometries([pcd])# ---- 可选:保存带颜色的点云 ----
# o3d.io.write_point_cloud("curvature_colored.ply", pcd)

计算结果可视化:
在这里插入图片描述

http://www.lryc.cn/news/610135.html

相关文章:

  • 八股——Kafka相关
  • 【Pytorch✨】LSTM04 l理解长期记忆和短期记忆
  • 第12届蓝桥杯Scratch_选拔赛_初级组_真题2020年8月23日
  • 神经网络---非线性激活
  • C++进阶-封装红黑树模拟实现map和set(难度较高)
  • 李沐写作笔记
  • 嵌入式 C 语言入门:函数指针基础笔记 —— 从计算器优化到指针本质
  • SurferCloud vs LightNode 海外云服务商详细对比
  • 【无标题】标准 I/O 中的一些函数,按功能分类说明其用法和特点
  • [特殊字符] 50 天 50 个项目 — 完结篇
  • 【Docker安装】Ubuntu 24.04.2 LTS系统下安装Docker环境——指定APT源安装方式
  • 基于MobileNet卷积神经网络和Xception神经网络算法的人脸表情识别系统的设计与实现
  • C语言的控制语句
  • 每日一leetcode:移动零
  • 【Java】HashMap线程安全吗?
  • allegro建库--1
  • 【云馨AI-大模型】2025年8月第一周AI浪潮席卷全球:创新与政策双轮驱动
  • MLS平滑滤波
  • 洛谷 P3373 【模板】线段树 2- 普及+/提高
  • 《Python 实用项目与工具制作指南》· 3.1 实战·开发题目数据生成器
  • 思科 UCS Fabric Interconnect 和 UCS Manager 简介
  • 比起登天,孙宇晨更需要安稳着陆
  • C语言编程中常用的预定义宏
  • 浅谈 Python 中的 next() 函数 —— 迭代器的驱动引擎
  • 【深度学习新浪潮】近三年城市级数字孪生的研究进展一览
  • push/pop字节对齐使用场景
  • Next Terminal 实战:内网无密码安全登录
  • cocos2 场景跳转传参
  • 佰力博检测与您探讨介温谱和介电谱的区别?
  • 【实战】Dify从0到100进阶--中药科普助手(1)