mission-voxelization.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. # 如此设定每个点占据的体积:确保比例为ratio_factor的点周围至少有neighbor_point_min_num个点和自己连通。
  2. import open3d as o3d
  3. import numpy as np
  4. import math
  5. import sys
  6. import random
  7. ratio_factor = 0.9
  8. neighbor_point_min_num = 8
  9. # 读取点云文件
  10. pcd = o3d.io.read_point_cloud("./data/PointClound_01.ply")
  11. print(pcd)
  12. # o3d.visualization.draw([pcd])
  13. # 原始点数量
  14. pcd_size = np.asarray(pcd.points).size / 3
  15. print('原始点数量:', pcd_size)
  16. # # 粗暴降采样
  17. # down_sampling_size = 1
  18. # pcd_down = pcd.voxel_down_sample(voxel_size=down_sampling_size)
  19. # pcd_down_size = np.asarray(pcd_down.points).size / 3
  20. # # 酌情降采样,直到点数量降到阈值以下
  21. # down_sampling_size = 0.01
  22. # pcd_down_size = float('inf')
  23. # while(pcd_down_size > 1000):
  24. # down_sampling_size = down_sampling_size + 0.02
  25. # pcd_down = pcd.voxel_down_sample(voxel_size=down_sampling_size)
  26. # pcd_down_size = np.asarray(pcd_down.points).size / 3
  27. # if down_sampling_size > 10:
  28. # break
  29. # print('降采样后点数量:', pcd_down_size)
  30. # print('降采样尺度:', down_sampling_size)
  31. # o3d.visualization.draw([pcd])
  32. # bbox情况
  33. # obb = pcd.get_oriented_bounding_box()
  34. # print('外包盒子体积:', obb.volume())
  35. # # fit to unit cube
  36. # pcd.scale(1 / np.max(pcd.get_max_bound() - pcd.get_min_bound()),
  37. # center=pcd.get_center())
  38. # o3d.visualization.draw_geometries([pcd])
  39. # 建立kd tree
  40. print('build kdtree...')
  41. pcd_tree = o3d.geometry.KDTreeFlann(pcd)
  42. print('build over')
  43. # 对每个采样点,记录其与周围点的距离
  44. sample_num = 0
  45. if pcd_size <= 10000:
  46. sample_num = pcd_size
  47. else:
  48. sample_num = 10000
  49. neighbor_dist_list = np.zeros([sample_num], dtype = float)
  50. for sampleIdx in range(0, math.floor(sample_num)):
  51. sampleIdxInPcd = random.randrange(0, pcd_size - 1, 1)
  52. neighbor_num = neighbor_point_min_num + 1 # 真正的最近的那个点是自己
  53. [k, neighbor_idx_list, _] = pcd_tree.search_knn_vector_3d(pcd.points[sampleIdxInPcd], neighbor_num)
  54. pointSample = np.asarray(pcd.points)[sampleIdxInPcd]
  55. for neighborIdx in range(1, neighbor_num):
  56. pointNeighbor = np.asarray(pcd.points)[neighbor_idx_list[neighborIdx]]
  57. 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))
  58. if new_val > neighbor_dist_list[sampleIdx]:
  59. neighbor_dist_list[sampleIdx] = new_val
  60. # print(neighbor_dist_list[sampleIdx])
  61. # if i < 100:
  62. # print('-------------')
  63. # print('iterate', i)
  64. # print(pointNeighbor, pointSample)
  65. # print(pointNeighbor[0] - pointSample[0])
  66. # print(math.pow(pointNeighbor[0] - pointSample[0], 2))
  67. # print(math.pow(pointNeighbor[0] - pointSample[0], 2) + math.pow(pointNeighbor[1] - pointSample[1], 2) + math.pow(pointNeighbor[2] - pointSample[2], 2))
  68. # print(neighbor_dist_list[i])
  69. # exit(0)
  70. # 确定素格尺寸
  71. voxel_size = 0
  72. neighbor_dist_min = np.min(neighbor_dist_list)
  73. neighbor_dist_max = np.max(neighbor_dist_list)
  74. print('距离最大值:', np.max(neighbor_dist_list))
  75. print('距离最小值:', np.min(neighbor_dist_list))
  76. if neighbor_dist_min == neighbor_dist_max:
  77. voxel_size = neighbor_dist_max
  78. else:
  79. binNum = 1000
  80. histogram = np.zeros((binNum), dtype = int)
  81. for sampleIdx in range(0, sample_num):
  82. belongBinIdx = math.floor((neighbor_dist_list[sampleIdx] - neighbor_dist_min) / (neighbor_dist_max - neighbor_dist_min) * binNum)
  83. if belongBinIdx == binNum:
  84. belongBinIdx = binNum - 1
  85. histogram[belongBinIdx] = histogram[belongBinIdx] + 1
  86. countThreshold = sample_num * ratio_factor
  87. countNow = 0
  88. for sampleIdx in range(0, binNum):
  89. print('-----------')
  90. print(histogram[sampleIdx], 'bin content value')
  91. countNow = countNow + histogram[sampleIdx]
  92. print(countNow, 'current total')
  93. if countNow >= countThreshold:
  94. voxel_size = neighbor_dist_min + (neighbor_dist_max - neighbor_dist_min) / binNum * (sampleIdx + 1)
  95. break
  96. print('voxel_size:', voxel_size)
  97. voxel_grid = o3d.geometry.VoxelGrid.create_from_point_cloud(pcd, voxel_size=voxel_size)
  98. print('voxel_grid: ', voxel_grid)
  99. total_volume = np.asarray(voxel_grid.get_voxels()).size * (math.pow(voxel_size, 3))
  100. print('点云占据体积:', total_volume)
  101. o3d.visualization.draw_geometries([voxel_grid])
  102. sys.exit(0)