voxelize_op.cc 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. // Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include <vector>
  15. #if defined(PADDLEINFERENCE_API_COMPAT_2_4_x)
  16. #include "paddle/include/experimental/ext_all.h"
  17. #elif defined(PADDLEINFERENCE_API_COMPAT_2_5_x)
  18. #include "paddle/include/paddle/extension.h"
  19. #else
  20. #include "paddle/extension.h"
  21. #endif
  22. namespace ultra_infer {
  23. namespace paddle_custom_ops {
  24. template <typename T, typename T_int>
  25. bool hard_voxelize_cpu_kernel(
  26. const T *points, const float point_cloud_range_x_min,
  27. const float point_cloud_range_y_min, const float point_cloud_range_z_min,
  28. const float voxel_size_x, const float voxel_size_y,
  29. const float voxel_size_z, const int grid_size_x, const int grid_size_y,
  30. const int grid_size_z, const int64_t num_points, const int num_point_dim,
  31. const int max_num_points_in_voxel, const int max_voxels, T *voxels,
  32. T_int *coords, T_int *num_points_per_voxel, T_int *grid_idx_to_voxel_idx,
  33. T_int *num_voxels) {
  34. std::fill(voxels,
  35. voxels + max_voxels * max_num_points_in_voxel * num_point_dim,
  36. static_cast<T>(0));
  37. num_voxels[0] = 0;
  38. int voxel_idx, grid_idx, curr_num_point;
  39. int coord_x, coord_y, coord_z;
  40. for (int point_idx = 0; point_idx < num_points; ++point_idx) {
  41. coord_x = floor(
  42. (points[point_idx * num_point_dim + 0] - point_cloud_range_x_min) /
  43. voxel_size_x);
  44. coord_y = floor(
  45. (points[point_idx * num_point_dim + 1] - point_cloud_range_y_min) /
  46. voxel_size_y);
  47. coord_z = floor(
  48. (points[point_idx * num_point_dim + 2] - point_cloud_range_z_min) /
  49. voxel_size_z);
  50. if (coord_x < 0 || coord_x > grid_size_x || coord_x == grid_size_x) {
  51. continue;
  52. }
  53. if (coord_y < 0 || coord_y > grid_size_y || coord_y == grid_size_y) {
  54. continue;
  55. }
  56. if (coord_z < 0 || coord_z > grid_size_z || coord_z == grid_size_z) {
  57. continue;
  58. }
  59. grid_idx =
  60. coord_z * grid_size_y * grid_size_x + coord_y * grid_size_x + coord_x;
  61. voxel_idx = grid_idx_to_voxel_idx[grid_idx];
  62. if (voxel_idx == -1) {
  63. voxel_idx = num_voxels[0];
  64. if (num_voxels[0] == max_voxels || num_voxels[0] > max_voxels) {
  65. continue;
  66. }
  67. num_voxels[0]++;
  68. grid_idx_to_voxel_idx[grid_idx] = voxel_idx;
  69. coords[voxel_idx * 3 + 0] = coord_z;
  70. coords[voxel_idx * 3 + 1] = coord_y;
  71. coords[voxel_idx * 3 + 2] = coord_x;
  72. }
  73. curr_num_point = num_points_per_voxel[voxel_idx];
  74. if (curr_num_point < max_num_points_in_voxel) {
  75. for (int j = 0; j < num_point_dim; ++j) {
  76. voxels[voxel_idx * max_num_points_in_voxel * num_point_dim +
  77. curr_num_point * num_point_dim + j] =
  78. points[point_idx * num_point_dim + j];
  79. }
  80. num_points_per_voxel[voxel_idx] = curr_num_point + 1;
  81. }
  82. }
  83. return true;
  84. }
  85. std::vector<paddle::Tensor>
  86. hard_voxelize_cpu(const paddle::Tensor &points,
  87. const std::vector<float> &voxel_size,
  88. const std::vector<float> &point_cloud_range,
  89. const int max_num_points_in_voxel, const int max_voxels) {
  90. auto num_points = points.shape()[0];
  91. auto num_point_dim = points.shape()[1];
  92. const float voxel_size_x = voxel_size[0];
  93. const float voxel_size_y = voxel_size[1];
  94. const float voxel_size_z = voxel_size[2];
  95. const float point_cloud_range_x_min = point_cloud_range[0];
  96. const float point_cloud_range_y_min = point_cloud_range[1];
  97. const float point_cloud_range_z_min = point_cloud_range[2];
  98. int grid_size_x = static_cast<int>(
  99. round((point_cloud_range[3] - point_cloud_range[0]) / voxel_size_x));
  100. int grid_size_y = static_cast<int>(
  101. round((point_cloud_range[4] - point_cloud_range[1]) / voxel_size_y));
  102. int grid_size_z = static_cast<int>(
  103. round((point_cloud_range[5] - point_cloud_range[2]) / voxel_size_z));
  104. auto voxels =
  105. paddle::empty({max_voxels, max_num_points_in_voxel, num_point_dim},
  106. paddle::DataType::FLOAT32, paddle::CPUPlace());
  107. auto coords = paddle::full({max_voxels, 3}, 0, paddle::DataType::INT32,
  108. paddle::CPUPlace());
  109. auto *coords_data = coords.data<int>();
  110. auto num_points_per_voxel = paddle::full(
  111. {max_voxels}, 0, paddle::DataType::INT32, paddle::CPUPlace());
  112. auto *num_points_per_voxel_data = num_points_per_voxel.data<int>();
  113. std::fill(num_points_per_voxel_data,
  114. num_points_per_voxel_data + num_points_per_voxel.size(),
  115. static_cast<int>(0));
  116. auto num_voxels =
  117. paddle::full({1}, 0, paddle::DataType::INT32, paddle::CPUPlace());
  118. auto *num_voxels_data = num_voxels.data<int>();
  119. auto grid_idx_to_voxel_idx =
  120. paddle::full({grid_size_z, grid_size_y, grid_size_x}, -1,
  121. paddle::DataType::INT32, paddle::CPUPlace());
  122. auto *grid_idx_to_voxel_idx_data = grid_idx_to_voxel_idx.data<int>();
  123. PD_DISPATCH_FLOATING_TYPES(
  124. points.type(), "hard_voxelize_cpu_kernel", ([&] {
  125. hard_voxelize_cpu_kernel<data_t, int>(
  126. points.data<data_t>(), point_cloud_range_x_min,
  127. point_cloud_range_y_min, point_cloud_range_z_min, voxel_size_x,
  128. voxel_size_y, voxel_size_z, grid_size_x, grid_size_y, grid_size_z,
  129. num_points, num_point_dim, max_num_points_in_voxel, max_voxels,
  130. voxels.data<data_t>(), coords_data, num_points_per_voxel_data,
  131. grid_idx_to_voxel_idx_data, num_voxels_data);
  132. }));
  133. return {voxels, coords, num_points_per_voxel, num_voxels};
  134. }
  135. #if defined(PADDLE_WITH_CUDA) && defined(WITH_GPU)
  136. std::vector<paddle::Tensor>
  137. hard_voxelize_cuda(const paddle::Tensor &points,
  138. const std::vector<float> &voxel_size,
  139. const std::vector<float> &point_cloud_range,
  140. int max_num_points_in_voxel, int max_voxels);
  141. #endif
  142. std::vector<paddle::Tensor>
  143. hard_voxelize(const paddle::Tensor &points,
  144. const std::vector<float> &voxel_size,
  145. const std::vector<float> &point_cloud_range,
  146. const int max_num_points_in_voxel, const int max_voxels) {
  147. if (points.is_cpu()) {
  148. return hard_voxelize_cpu(points, voxel_size, point_cloud_range,
  149. max_num_points_in_voxel, max_voxels);
  150. #if defined(PADDLE_WITH_CUDA) && defined(WITH_GPU)
  151. } else if (points.is_gpu() || points.is_gpu_pinned()) {
  152. return hard_voxelize_cuda(points, voxel_size, point_cloud_range,
  153. max_num_points_in_voxel, max_voxels);
  154. #endif
  155. } else {
  156. PD_THROW("Unsupported device type for hard_voxelize "
  157. "operator.");
  158. }
  159. }
  160. std::vector<std::vector<int64_t>>
  161. HardInferShape(std::vector<int64_t> points_shape,
  162. const std::vector<float> &voxel_size,
  163. const std::vector<float> &point_cloud_range,
  164. const int &max_num_points_in_voxel, const int &max_voxels) {
  165. return {{max_voxels, max_num_points_in_voxel, points_shape[1]},
  166. {max_voxels, 3},
  167. {max_voxels},
  168. {1}};
  169. }
  170. std::vector<paddle::DataType> HardInferDtype(paddle::DataType points_dtype) {
  171. return {points_dtype, paddle::DataType::INT32, paddle::DataType::INT32,
  172. paddle::DataType::INT32};
  173. }
  174. } // namespace paddle_custom_ops
  175. } // namespace ultra_infer
  176. PD_BUILD_OP(hard_voxelize)
  177. .Inputs({"POINTS"})
  178. .Outputs({"VOXELS", "COORS", "NUM_POINTS_PER_VOXEL", "num_voxels"})
  179. .SetKernelFn(PD_KERNEL(ultra_infer::paddle_custom_ops::hard_voxelize))
  180. .Attrs({"voxel_size: std::vector<float>",
  181. "point_cloud_range: std::vector<float>",
  182. "max_num_points_in_voxel: int", "max_voxels: int"})
  183. .SetInferShapeFn(
  184. PD_INFER_SHAPE(ultra_infer::paddle_custom_ops::HardInferShape))
  185. .SetInferDtypeFn(
  186. PD_INFER_DTYPE(ultra_infer::paddle_custom_ops::HardInferDtype));