123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- # 如此设定每个点占据的体积:确保比例为ratio_factor的点周围至少有neighbor_point_min_num个点和自己连通。
- import open3d as o3d
- import numpy as np
- import math
- import sys
- import random
- ratio_factor = 0.9
- neighbor_point_min_num = 8
- # 读取点云文件
- pcd = o3d.io.read_point_cloud("./data/PointClound_01.ply")
- print(pcd)
- # o3d.visualization.draw([pcd])
- # 原始点数量
- pcd_size = np.asarray(pcd.points).size / 3
- print('原始点数量:', pcd_size)
- # # 粗暴降采样
- # down_sampling_size = 1
- # pcd_down = pcd.voxel_down_sample(voxel_size=down_sampling_size)
- # pcd_down_size = np.asarray(pcd_down.points).size / 3
- # # 酌情降采样,直到点数量降到阈值以下
- # down_sampling_size = 0.01
- # pcd_down_size = float('inf')
- # while(pcd_down_size > 1000):
- # down_sampling_size = down_sampling_size + 0.02
- # pcd_down = pcd.voxel_down_sample(voxel_size=down_sampling_size)
- # pcd_down_size = np.asarray(pcd_down.points).size / 3
- # if down_sampling_size > 10:
- # break
- # print('降采样后点数量:', pcd_down_size)
- # print('降采样尺度:', down_sampling_size)
- # o3d.visualization.draw([pcd])
- # bbox情况
- # obb = pcd.get_oriented_bounding_box()
- # print('外包盒子体积:', obb.volume())
- # # fit to unit cube
- # pcd.scale(1 / np.max(pcd.get_max_bound() - pcd.get_min_bound()),
- # center=pcd.get_center())
- # o3d.visualization.draw_geometries([pcd])
- # 建立kd tree
- print('build kdtree...')
- pcd_tree = o3d.geometry.KDTreeFlann(pcd)
- print('build over')
- # 对每个采样点,记录其与周围点的距离
- sample_num = 0
- if pcd_size <= 10000:
- sample_num = pcd_size
- else:
- sample_num = 10000
- neighbor_dist_list = np.zeros([sample_num], dtype = float)
- for sampleIdx in range(0, math.floor(sample_num)):
- sampleIdxInPcd = random.randrange(0, pcd_size - 1, 1)
- neighbor_num = neighbor_point_min_num + 1 # 真正的最近的那个点是自己
- [k, neighbor_idx_list, _] = pcd_tree.search_knn_vector_3d(pcd.points[sampleIdxInPcd], neighbor_num)
- pointSample = np.asarray(pcd.points)[sampleIdxInPcd]
- for neighborIdx in range(1, neighbor_num):
- pointNeighbor = np.asarray(pcd.points)[neighbor_idx_list[neighborIdx]]
- new_val = math.sqrt(math.pow(pointNeighbor[0] - pointSample[0], 2) + math.pow(pointNeighbor[1] - pointSample[1], 2) + math.pow(pointNeighbor[2] - pointSample[2], 2))
- if new_val > neighbor_dist_list[sampleIdx]:
- neighbor_dist_list[sampleIdx] = new_val
- # print(neighbor_dist_list[sampleIdx])
- # if i < 100:
- # print('-------------')
- # print('iterate', i)
- # print(pointNeighbor, pointSample)
- # print(pointNeighbor[0] - pointSample[0])
- # print(math.pow(pointNeighbor[0] - pointSample[0], 2))
- # print(math.pow(pointNeighbor[0] - pointSample[0], 2) + math.pow(pointNeighbor[1] - pointSample[1], 2) + math.pow(pointNeighbor[2] - pointSample[2], 2))
- # print(neighbor_dist_list[i])
- # exit(0)
- # 确定素格尺寸
- voxel_size = 0
- neighbor_dist_min = np.min(neighbor_dist_list)
- neighbor_dist_max = np.max(neighbor_dist_list)
- print('距离最大值:', np.max(neighbor_dist_list))
- print('距离最小值:', np.min(neighbor_dist_list))
- if neighbor_dist_min == neighbor_dist_max:
- voxel_size = neighbor_dist_max
- else:
- binNum = 1000
- histogram = np.zeros((binNum), dtype = int)
- for sampleIdx in range(0, sample_num):
- belongBinIdx = math.floor((neighbor_dist_list[sampleIdx] - neighbor_dist_min) / (neighbor_dist_max - neighbor_dist_min) * binNum)
- if belongBinIdx == binNum:
- belongBinIdx = binNum - 1
- histogram[belongBinIdx] = histogram[belongBinIdx] + 1
- countThreshold = sample_num * ratio_factor
- countNow = 0
- for sampleIdx in range(0, binNum):
- print('-----------')
- print(histogram[sampleIdx], 'bin content value')
- countNow = countNow + histogram[sampleIdx]
- print(countNow, 'current total')
- if countNow >= countThreshold:
- voxel_size = neighbor_dist_min + (neighbor_dist_max - neighbor_dist_min) / binNum * (sampleIdx + 1)
- break
- print('voxel_size:', voxel_size)
- voxel_grid = o3d.geometry.VoxelGrid.create_from_point_cloud(pcd, voxel_size=voxel_size)
- print('voxel_grid: ', voxel_grid)
- total_volume = np.asarray(voxel_grid.get_voxels()).size * (math.pow(voxel_size, 3))
- print('点云占据体积:', total_volume)
- o3d.visualization.draw_geometries([voxel_grid])
- sys.exit(0)
|