mission-2d-slice-sum.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. import open3d as o3d
  2. import numpy as np
  3. import math
  4. import math
  5. from functools import reduce
  6. import sys
  7. import copy
  8. import random
  9. ratio_factor = 0.9
  10. neighbor_point_min_num = 8
  11. # pcd = o3d.io.read_point_cloud("data/stockpile.ply")
  12. pcd = o3d.io.read_point_cloud("data/2box-SG-t-MnQ0zoEQIBX.ply")
  13. # pcd = o3d.io.read_point_cloud("data/4box-1-SG-t-AsSRO3iA0XT.ply")
  14. # pcd = o3d.io.read_point_cloud("data/4box-2-SG-t-cp3kSewxMKi.ply")
  15. # pcd = o3d.io.read_point_cloud("data/4box-3-SG-t-kuuv0moEP0C.ply")
  16. print(pcd)
  17. assert (pcd.has_normals())
  18. o3d.visualization.draw_geometries([pcd])
  19. axes = o3d.geometry.TriangleMesh.create_coordinate_frame()
  20. # 找出地面所在平面
  21. plane_model, inliers = pcd.segment_plane(distance_threshold=0.01,
  22. ransac_n=3,
  23. num_iterations=10000)
  24. # 把地面上的点和其他点分开
  25. [a, b, c, d] = plane_model
  26. plane_pcd = pcd.select_by_index(inliers)
  27. plane_pcd.paint_uniform_color([1.0, 0, 0])
  28. stockpile_pcd = pcd.select_by_index(inliers, invert=True)
  29. # stockpile_pcd = pcd
  30. stockpile_pcd.paint_uniform_color([0, 0, 1.0])
  31. o3d.visualization.draw_geometries([plane_pcd, stockpile_pcd, axes])
  32. # 移动到原点
  33. plane_pcd = plane_pcd.translate((0,0,d/c))
  34. stockpile_pcd = stockpile_pcd.translate((0,0,d/c))
  35. # 旋转至与坐标轴对齐
  36. cos_theta = c / math.sqrt(a**2 + b**2 + c**2)
  37. sin_theta = math.sqrt((a**2+b**2)/(a**2 + b**2 + c**2))
  38. u_1 = b / math.sqrt(a**2 + b**2 )
  39. u_2 = -a / math.sqrt(a**2 + b**2)
  40. rotation_matrix = np.array([[cos_theta + u_1**2 * (1-cos_theta), u_1*u_2*(1-cos_theta), u_2*sin_theta],
  41. [u_1*u_2*(1-cos_theta), cos_theta + u_2**2*(1- cos_theta), -u_1*sin_theta],
  42. [-u_2*sin_theta, u_1*sin_theta, cos_theta]])
  43. plane_pcd.rotate(rotation_matrix)
  44. stockpile_pcd.rotate(rotation_matrix)
  45. o3d.visualization.draw_geometries([plane_pcd, stockpile_pcd, axes])
  46. # 用statistical outlier算法去除噪点
  47. cl, ind = stockpile_pcd.remove_statistical_outlier(nb_neighbors=100,
  48. std_ratio=1)
  49. stockpile_pcd = stockpile_pcd.select_by_index(ind)
  50. # 降采样
  51. # downpcd = stockpile_pcd.voxel_down_sample(voxel_size=0.1)
  52. downpcd = stockpile_pcd
  53. print('有效点云:', np.asarray(downpcd.points))
  54. # 建立三维网格
  55. bbox = downpcd.get_axis_aligned_bounding_box()
  56. my_bbox = {
  57. 'min_bound': (bbox.min_bound[0], bbox.min_bound[1], bbox.min_bound[2]),
  58. 'max_bound': ((bbox.max_bound[0], bbox.max_bound[1], bbox.max_bound[2] + 0.5)),
  59. }
  60. print('my_bbox: ', my_bbox)
  61. bin_num_1d = 30
  62. bin_size_x = (my_bbox['max_bound'][0] - my_bbox['min_bound'][0]) / bin_num_1d
  63. bin_size_y = (my_bbox['max_bound'][1] - my_bbox['min_bound'][1]) / bin_num_1d
  64. bin_size_z = (my_bbox['max_bound'][2] - my_bbox['min_bound'][2]) / bin_num_1d
  65. grid = np.zeros((bin_num_1d, bin_num_1d, bin_num_1d))
  66. print('bin_size: ', bin_size_x, bin_size_y, bin_size_z)
  67. points = np.asarray(downpcd.points)
  68. for point in points:
  69. bin_idx_x = math.floor((point[0] - my_bbox['min_bound'][0]) / (my_bbox['max_bound'][0] - my_bbox['min_bound'][0]) * bin_num_1d)
  70. if bin_idx_x <= -1: # 浮点数溢出
  71. bin_idx_x = 0
  72. if bin_idx_x >= bin_num_1d:
  73. bin_idx_x = bin_num_1d - 1
  74. bin_idx_y = math.floor((point[1] - my_bbox['min_bound'][1]) / (my_bbox['max_bound'][1] - my_bbox['min_bound'][1]) * bin_num_1d)
  75. if bin_idx_y <= -1: # 浮点数溢出
  76. bin_idx_y = 0
  77. if bin_idx_y >= bin_num_1d:
  78. bin_idx_y = bin_num_1d - 1
  79. bin_idx_z = math.floor((point[2] - my_bbox['min_bound'][2]) / (my_bbox['max_bound'][2] - my_bbox['min_bound'][2]) * bin_num_1d)
  80. if bin_idx_z <= -1: # 浮点数溢出
  81. bin_idx_z = 0
  82. if bin_idx_z >= bin_num_1d:
  83. bin_idx_z = bin_num_1d - 1
  84. # print('point', point)
  85. # print(grid[bin_idx_x, bin_idx_y, bin_idx_z])
  86. grid[bin_idx_x, bin_idx_y, bin_idx_z] += 1
  87. min_point_num_threshold = 1
  88. assert(grid[0, 0, bin_num_1d - 1] < min_point_num_threshold)
  89. grid_voxel = np.zeros((bin_num_1d, bin_num_1d, bin_num_1d)) # 0: 初始状态;-1:已加入待处理列表; 1:已处理,无点;2:已处理,有点;
  90. cellToProcessList = [(0, 0, bin_num_1d - 1)]
  91. grid_voxel[0, 0, bin_num_1d - 1] = -1
  92. count1 = 0
  93. count2 = 0
  94. def processCell():
  95. global min_point_num_threshold
  96. global grid
  97. global grid_voxel
  98. global cellToProcessList
  99. global count1
  100. global count2
  101. i = cellToProcessList[0][0]
  102. j = cellToProcessList[0][1]
  103. k = cellToProcessList[0][2]
  104. assert(grid_voxel[i, j, k] == -1)
  105. if grid[i, j, k] < min_point_num_threshold:
  106. grid_voxel[i, j, k] = 1
  107. count1 += 1
  108. if i - 1 >= 0 and grid_voxel[i - 1, j, k] == 0:
  109. cellToProcessList.append((i - 1, j, k))
  110. grid_voxel[i - 1, j, k] = -1
  111. if i + 1 <= bin_num_1d - 1 and grid_voxel[i + 1, j, k] == 0:
  112. cellToProcessList.append((i + 1, j, k))
  113. grid_voxel[i + 1, j, k] = -1
  114. if j - 1 >= 0 and grid_voxel[i, j - 1, k] == 0:
  115. cellToProcessList.append((i, j - 1, k))
  116. grid_voxel[i, j - 1, k] = -1
  117. if j + 1 <= bin_num_1d - 1 and grid_voxel[i, j + 1, k] == 0:
  118. cellToProcessList.append((i, j + 1, k))
  119. grid_voxel[i, j + 1, k] = -1
  120. if k - 1 >= 0 and grid_voxel[i, j, k - 1] == 0:
  121. cellToProcessList.append((i, j, k - 1))
  122. grid_voxel[i, j, k - 1] = -1
  123. if k + 1 <= bin_num_1d - 1 and grid_voxel[i, j, k + 1] == 0:
  124. cellToProcessList.append((i, j, k + 1))
  125. grid_voxel[i, j, k + 1] = -1
  126. else:
  127. grid_voxel[i, j, k] = 2
  128. count2 += 1
  129. cellToProcessList.pop(0)
  130. while len(cellToProcessList) > 0:
  131. processCell()
  132. print('空虚格子数:', count1)
  133. print('边界格子数:', count2)
  134. print('内部格子数:', bin_num_1d * bin_num_1d * bin_num_1d - count1 - 0.5 * count2)
  135. print('物体占比:', (bin_num_1d * bin_num_1d * bin_num_1d - count1 - 0.5 * count2) / (bin_num_1d * bin_num_1d * bin_num_1d))
  136. print('体积:', (bin_num_1d * bin_num_1d * bin_num_1d - count1 - 0.5 * count2) * bin_size_x * bin_size_y * bin_size_z)
  137. print('外部体积:', (count1 + 0.5 * count2) * bin_size_x * bin_size_y * bin_size_z)
  138. print('0, 0, 最高:', grid_voxel[0, 0, bin_num_1d - 1])
  139. print('0, 0, 最低:', grid_voxel[0, 0, 0])