Python进行点云公共区域的提取
本节我们分享点云点云公共区域的提取。在点云处理任务中,明确划分“公共区”与“非公共区”不仅是几何上的切分,更是后续算法成败的关键。其作用可以从五个维度加以概括:
1. 配准可信度计
多视角拼接后,公共区的几何一致性直接反映配准精度。公共面越大、误差越小,说明外参与内参估计越可靠,可据此给出量化的“配准置信度”。2. 重建完整性保障
三维模型要无缝,必须依赖足够且分布均匀的公共区。该区域为 ICP、BA 等算法提供交叉约束,使不同视角的曲面在融合时既保持细节又抑制漂移。3. 数据融合决策
当把多块扫描合并成一张“大图”时,公共区就是天然的“缝合带”。算法可在此区域内做加权平均、体素融合或表面优化,从而保证整体点云密度一致、无裂缝。4. 噪声与冗余抑制
非公共区往往包含传感器边缘噪声、离群点或重复扫描的冗余数据。将其单独提取后,可用统计滤波、空间聚类等手段快速剔除,提高整体信噪比。5. 差异监测与变更识别
同一地点、不同时间采集的两片点云,通过公共区配准后,非公共区即为“变化区域”。在建筑监测、工地进度跟踪等场景中,可据此自动检测新增结构或拆除部分,实现厘米级变更量化。
本次我们使用的依然是老朋友,出来吧,召唤兔神!
一、点云公共区域的提取程序
点击程序,选取点云,出现结果,over!
import sys
from pathlib import Path
import tkinter as tk
from tkinter import filedialog, messageboximport numpy as np
import open3d as o3d
import copydef ask(title: str) -> Path:"""弹出文件选择框,返回选中的文件路径。"""root = tk.Tk()root.withdraw()f = filedialog.askopenfilename(title=title,filetypes=[("点云文件", "*.ply *.pcd *.xyz"), ("所有文件", "*.*")])root.destroy()if not f:sys.exit(0)return Path(f)def load(p: Path) -> o3d.geometry.PointCloud:cloud = o3d.io.read_point_cloud(str(p))if cloud.is_empty():raise RuntimeError(f"无法读取:{p}")return clouddef main():try:# 选文件 Aa_path = ask("请选择第一个点云(A)")pc_a = load(a_path)# 选文件 B# b_path = ask("请选择第二个点云(B)")# pc_b = load(b_path)# 如果选择文件B,将下面这一段关于pc_b的处理去掉pc_b = copy.deepcopy(pc_a)points = np.asarray(pc_b.points)t = np.array([0, 0, 0])pc_b = pc_b.translate(t, relative=True) # relative=True 表示“增量”平移# 加噪声mu, sigma = 0, 0.001 # 均值和标准差根据密度调节random_numbers = np.random.normal(mu, sigma, size=(points.shape[0], 3))points += random_numberspc_b.points = o3d.utility.Vector3dVector(points)pc_b.paint_uniform_color([0, 1, 0]) # 给目标点云赋予单色# 距离阈值(固定 1.0,想改直接改下面数字即可)thr = 0.001# 计算距离dists = np.asarray(pc_b.compute_point_cloud_distance(pc_a))inlier_idx = np.where(dists < thr)[0]# 分成两部分并上色inliers = pc_b.select_by_index(inlier_idx).paint_uniform_color([1, 1, 0])outliers = pc_b.select_by_index(inlier_idx, invert=True).paint_uniform_color([1, 0, 0])# 依次显示o3d.visualization.draw_geometries([pc_a, pc_b], "原始点云 A 与 B")o3d.visualization.draw_geometries([inliers, outliers],f"重叠(黄) & 非重叠(红) 阈值={thr}")except Exception as e:messagebox.showerror("出错了!", str(e))if __name__ == "__main__":main()
二、点云公共区域的提取结果
从结果可以看出,算法还是很成功的。不过动手做的细心的同学们可以发现另一个事儿,如果距离调的很近,哪怕是同一个点云,也会出现提取不出来的情况。这可能就是数据处理过程中的偏差。就酱,下次见^-^