"docs/vscode:/vscode.git/clone" did not exist on "e15431b76f2c0ef4d8c59c37b90e667b6a7fb915"
voxelization_cpu.cpp 5.85 KB
Newer Older
zhangwenwei's avatar
zhangwenwei committed
1
#include <ATen/TensorUtils.h>
2
#include <torch/extension.h>
zhangwenwei's avatar
zhangwenwei committed
3
4
5
6
7
// #include "voxelization.h"

namespace {

template <typename T, typename T_int>
8
void dynamic_voxelize_kernel(const torch::TensorAccessor<T, 2> points,
zhangwenwei's avatar
zhangwenwei committed
9
10
11
12
                             torch::TensorAccessor<T_int, 2> coors,
                             const std::vector<float> voxel_size,
                             const std::vector<float> coors_range,
                             const std::vector<int> grid_size,
13
14
                             const int num_points, const int num_features,
                             const int NDim) {
zhangwenwei's avatar
zhangwenwei committed
15
16
  const int ndim_minus_1 = NDim - 1;
  bool failed = false;
17
18
  // int coor[NDim];
  int* coor = new int[NDim]();
zhangwenwei's avatar
zhangwenwei committed
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
  int c;

  for (int i = 0; i < num_points; ++i) {
    failed = false;
    for (int j = 0; j < NDim; ++j) {
      c = floor((points[i][j] - coors_range[j]) / voxel_size[j]);
      // necessary to rm points out of range
      if ((c < 0 || c >= grid_size[j])) {
        failed = true;
        break;
      }
      coor[ndim_minus_1 - j] = c;
    }

    for (int k = 0; k < NDim; ++k) {
      if (failed)
        coors[i][k] = -1;
      else
        coors[i][k] = coor[k];
    }
  }

41
  delete[] coor;
zhangwenwei's avatar
zhangwenwei committed
42
43
44
45
  return;
}

template <typename T, typename T_int>
46
47
48
49
50
51
void hard_voxelize_kernel(const torch::TensorAccessor<T, 2> points,
                          torch::TensorAccessor<T, 3> voxels,
                          torch::TensorAccessor<T_int, 2> coors,
                          torch::TensorAccessor<T_int, 1> num_points_per_voxel,
                          torch::TensorAccessor<T_int, 3> coor_to_voxelidx,
                          int& voxel_num, const std::vector<float> voxel_size,
zhangwenwei's avatar
zhangwenwei committed
52
53
                          const std::vector<float> coors_range,
                          const std::vector<int> grid_size,
54
55
56
                          const int max_points, const int max_voxels,
                          const int num_points, const int num_features,
                          const int NDim) {
zhangwenwei's avatar
zhangwenwei committed
57
  // declare a temp coors
58
59
  at::Tensor temp_coors = at::zeros(
      {num_points, NDim}, at::TensorOptions().dtype(at::kInt).device(at::kCPU));
zhangwenwei's avatar
zhangwenwei committed
60
61
62

  // First use dynamic voxelization to get coors,
  // then check max points/voxels constraints
63
64
65
  dynamic_voxelize_kernel<T, int>(points, temp_coors.accessor<int, 2>(),
                                  voxel_size, coors_range, grid_size,
                                  num_points, num_features, NDim);
zhangwenwei's avatar
zhangwenwei committed
66
67

  int voxelidx, num;
68
  auto coor = temp_coors.accessor<int, 2>();
zhangwenwei's avatar
zhangwenwei committed
69
70
71
72

  for (int i = 0; i < num_points; ++i) {
    // T_int* coor = temp_coors.data_ptr<int>() + i * NDim;

73
    if (coor[i][0] == -1) continue;
zhangwenwei's avatar
zhangwenwei committed
74
75
76
77
78
79

    voxelidx = coor_to_voxelidx[coor[i][0]][coor[i][1]][coor[i][2]];

    // record voxel
    if (voxelidx == -1) {
      voxelidx = voxel_num;
80
      if (max_voxels != -1 && voxel_num >= max_voxels) continue;
zhangwenwei's avatar
zhangwenwei committed
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
      voxel_num += 1;

      coor_to_voxelidx[coor[i][0]][coor[i][1]][coor[i][2]] = voxelidx;

      for (int k = 0; k < NDim; ++k) {
        coors[voxelidx][k] = coor[i][k];
      }
    }

    // put points into voxel
    num = num_points_per_voxel[voxelidx];
    if (max_points == -1 || num < max_points) {
      for (int k = 0; k < num_features; ++k) {
        voxels[voxelidx][num][k] = points[i][k];
      }
      num_points_per_voxel[voxelidx] += 1;
    }
  }

  return;
}

103
}  // namespace
zhangwenwei's avatar
zhangwenwei committed
104
105
106

namespace voxelization {

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
int hard_voxelize_cpu(const at::Tensor& points, at::Tensor& voxels,
                      at::Tensor& coors, at::Tensor& num_points_per_voxel,
                      const std::vector<float> voxel_size,
                      const std::vector<float> coors_range,
                      const int max_points, const int max_voxels,
                      const int NDim = 3) {
  // current version tooks about 0.02s_0.03s for one frame on cpu
  // check device
  AT_ASSERTM(points.device().is_cpu(), "points must be a CPU tensor");

  std::vector<int> grid_size(NDim);
  const int num_points = points.size(0);
  const int num_features = points.size(1);

  for (int i = 0; i < NDim; ++i) {
    grid_size[i] =
        round((coors_range[NDim + i] - coors_range[i]) / voxel_size[i]);
  }
zhangwenwei's avatar
zhangwenwei committed
125

126
127
128
129
130
  // coors, num_points_per_voxel, coor_to_voxelidx are int Tensor
  // printf("cpu coor_to_voxelidx size: [%d, %d, %d]\n", grid_size[2],
  // grid_size[1], grid_size[0]);
  at::Tensor coor_to_voxelidx =
      -at::ones({grid_size[2], grid_size[1], grid_size[0]}, coors.options());
zhangwenwei's avatar
zhangwenwei committed
131

132
133
134
  int voxel_num = 0;
  AT_DISPATCH_FLOATING_TYPES_AND_HALF(
      points.scalar_type(), "hard_voxelize_forward", [&] {
zhangwenwei's avatar
zhangwenwei committed
135
        hard_voxelize_kernel<scalar_t, int>(
136
137
138
139
140
141
142
143
            points.accessor<scalar_t, 2>(), voxels.accessor<scalar_t, 3>(),
            coors.accessor<int, 2>(), num_points_per_voxel.accessor<int, 1>(),
            coor_to_voxelidx.accessor<int, 3>(), voxel_num, voxel_size,
            coors_range, grid_size, max_points, max_voxels, num_points,
            num_features, NDim);
      });

  return voxel_num;
zhangwenwei's avatar
zhangwenwei committed
144
145
}

146
147
148
149
150
151
void dynamic_voxelize_cpu(const at::Tensor& points, at::Tensor& coors,
                          const std::vector<float> voxel_size,
                          const std::vector<float> coors_range,
                          const int NDim = 3) {
  // check device
  AT_ASSERTM(points.device().is_cpu(), "points must be a CPU tensor");
zhangwenwei's avatar
zhangwenwei committed
152

153
154
155
  std::vector<int> grid_size(NDim);
  const int num_points = points.size(0);
  const int num_features = points.size(1);
zhangwenwei's avatar
zhangwenwei committed
156

157
158
159
160
  for (int i = 0; i < NDim; ++i) {
    grid_size[i] =
        round((coors_range[NDim + i] - coors_range[i]) / voxel_size[i]);
  }
zhangwenwei's avatar
zhangwenwei committed
161

162
163
164
  // coors, num_points_per_voxel, coor_to_voxelidx are int Tensor
  AT_DISPATCH_FLOATING_TYPES_AND_HALF(
      points.scalar_type(), "hard_voxelize_forward", [&] {
zhangwenwei's avatar
zhangwenwei committed
165
        dynamic_voxelize_kernel<scalar_t, int>(
166
167
168
            points.accessor<scalar_t, 2>(), coors.accessor<int, 2>(),
            voxel_size, coors_range, grid_size, num_points, num_features, NDim);
      });
zhangwenwei's avatar
zhangwenwei committed
169

170
  return;
zhangwenwei's avatar
zhangwenwei committed
171
}
172
173

}  // namespace voxelization