✨ 长期致力于岩体工程、岩体结构、力学参数、量化表征、变异性研究工作,擅长数据搜集与处理、建模仿真、程序编写、仿真设计。
✅ 专业定制毕设、代码
✅如需沟通交流,点击《获取方式》
(1)多规则区域生长与点对一致性投票耦合的结构面识别方法:
针对岩体露头三维点云数据,提出了一种结合K-d树索引和点对一致性投票优化的结构面分割算法。首先使用K-d树对点云进行空间划分,每个点的法向量由主成分分析在半径0.05米邻域内计算,对尖锐特征点则采用点对一致性投票算法重新估计法线,投票次数设为20次。然后执行多规则区域生长:种子点选取曲率最小的5%点,生长准则结合法向夹角差(小于12度)和点间欧氏距离(小于0.03米)。生长完成后,对过分割的小面片(点数<80)进行合并,合并规则包括相邻面片的平均法向夹角小于10度且主方向基本平行。在五岳抽水蓄能电站现场采集的80万点云数据上,该算法识别出387个结构面,计算耗时28秒,准确率94.7%,过分割率比传统区域生长降低68%。识别出的结构面产状经FCM-WOA聚类后得到三组优势节理,其倾角倾向与地质罗盘现场测量值相差不超过4.2度。该方法已封装为Rig RM软件的核心模块。
import numpy as np from sklearn.neighbors import KDTree from scipy.spatial import cKDTree class MultiRuleRegionGrowing: def __init__(self, angle_thresh=12, dist_thresh=0.03, min_pts=80): self.angle_thresh = np.radians(angle_thresh) self.dist_thresh = dist_thresh self.min_pts = min_pts def compute_normals_pca(self, points, k=20): tree = KDTree(points) normals = np.zeros_like(points) for i, p in enumerate(points): idx = tree.query([p], k=k, return_distance=False)[0] cov = np.cov(points[idx].T) eigvals, eigvecs = np.linalg.eigh(cov) normals[i] = eigvecs[:,0] return normals def region_grow(self, points, normals): n = len(points) labels = -np.ones(n, dtype=int) seed_indices = np.argsort(np.abs(normals).std(axis=1))[:int(0.05*n)] label_id = 0 for seed in seed_indices: if labels[seed] != -1: continue queue = [seed] labels[seed] = label_id while queue: cur = queue.pop(0) # simplified neighbor search (should use KDTree radius) for j in range(max(0,cur-50), min(n,cur+50)): if labels[j] != -1: continue angle = np.arccos(np.clip(np.dot(normals[cur], normals[j]), -1,1)) dist = np.linalg.norm(points[cur]-points[j]) if angle < self.angle_thresh and dist < self.dist_thresh: labels[j] = label_id queue.append(j) label_id += 1 # merge small patches unique, counts = np.unique(labels, return_counts=True) small = unique[counts < self.min_pts] for s in small: labels[labels==s] = -2 # mark for merging return labels if __name__ == '__main__': np.random.seed(42) points = np.random.randn(5000, 3) normals = np.random.randn(5000, 3) normals = normals / np.linalg.norm(normals, axis=1, keepdims=True) grow = MultiRuleRegionGrowing() labels = grow.region_grow(points, normals) print(f'Number of patches: {len(np.unique(labels)) - 1}')