Open3D (C++ API)  0.19.0
ContinuousConv.h
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - Open3D: www.open3d.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.open3d.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #pragma once
9 
10 #include <tbb/parallel_for.h>
11 
13 
14 namespace open3d {
15 namespace ml {
16 namespace impl {
17 
20 template <class TFeat,
21  class TOut,
22  class TReal,
23  class TIndex,
24  InterpolationMode INTERPOLATION,
25  CoordinateMapping MAPPING,
26  bool ALIGN_CORNERS,
27  bool INDIVIDUAL_EXTENT,
28  bool ISOTROPIC_EXTENT,
29  bool POINT_IMPORTANCE>
30 void _CConvComputeFeaturesCPU(TOut* out_features,
31  const std::vector<int>& filter_dims,
32  const TFeat* filter,
33  size_t num_out,
34  const TReal* out_positions,
35  size_t num_inp,
36  const TReal* inp_positions,
37  const TFeat* inp_features,
38  const TFeat* inp_importance,
39  size_t neighbors_index_size,
40  const TIndex* neighbors_index,
41  const TFeat* neighbors_importance,
42  const int64_t* neighbors_row_splits,
43  const TReal* extents,
44  const TReal* offsets,
45  bool normalize) {
46  const bool NEIGHBORS_IMPORTANCE = neighbors_importance != nullptr;
47  const int VECSIZE = 32;
48  typedef Eigen::Array<TReal, VECSIZE, 1> Vec_t;
49  typedef InterpolationVec<TReal, VECSIZE, INTERPOLATION> InterpolationVec_t;
50  InterpolationVec_t interpolation;
51 
52  const int in_channels = filter_dims[filter_dims.size() - 2];
53  const int out_channels = filter_dims[filter_dims.size() - 1];
54 
55  int spatial_filter_size = 1;
56  for (int i = 0; i < 3; ++i) spatial_filter_size *= filter_dims[i];
57  Eigen::Array<int, 3, 1> filter_size_xyz(filter_dims[2], filter_dims[1],
58  filter_dims[0]);
59 
60  memset(out_features, 0, sizeof(TOut) * num_out * out_channels);
61 
62  typedef Eigen::Array<TFeat, VECSIZE, Eigen::Dynamic> Matrix;
63  typedef Eigen::Array<TReal, VECSIZE, 3> Matrix3C;
64 
65  tbb::parallel_for(
66  tbb::blocked_range<size_t>(0, num_out, 32),
67  [&](const tbb::blocked_range<size_t>& r) {
68  int range_length = r.end() - r.begin();
69 
70  Eigen::Matrix<TOut, Eigen::Dynamic, 1> normalizers(range_length,
71  1);
72  normalizers.setZero();
73 
74  Eigen::Matrix<TFeat, Eigen::Dynamic, Eigen::Dynamic> B(
75  in_channels * spatial_filter_size, range_length);
76  B.setZero();
77 
78  Matrix infeat(VECSIZE, in_channels);
79 
80  Eigen::Array<TReal, 3, 1> offsets_(offsets[0], offsets[1],
81  offsets[2]);
82 
83  Matrix3C inv_extents;
84  if (INDIVIDUAL_EXTENT == false) {
85  if (ISOTROPIC_EXTENT) {
86  inv_extents = 1 / extents[0];
87  } else {
88  inv_extents.col(0) = 1 / extents[0];
89  inv_extents.col(1) = 1 / extents[1];
90  inv_extents.col(2) = 1 / extents[2];
91  }
92  }
93 
94  for (size_t out_idx = r.begin(); out_idx != r.end();
95  ++out_idx) {
96  const int out_col = out_idx - r.begin();
97  const size_t neighbor_start = neighbors_row_splits[out_idx];
98  const size_t neighbor_end =
99  neighbors_row_splits[out_idx + 1];
100 
101  if (INDIVIDUAL_EXTENT) {
102  if (ISOTROPIC_EXTENT) {
103  inv_extents = 1 / extents[out_idx];
104  } else {
105  inv_extents.col(0) = 1 / extents[3 * out_idx + 0];
106  inv_extents.col(1) = 1 / extents[3 * out_idx + 1];
107  inv_extents.col(2) = 1 / extents[3 * out_idx + 2];
108  }
109  }
110 
111  typename InterpolationVec_t::Weight_t interp_weights;
112  typename InterpolationVec_t::Idx_t interp_indices;
113 
114  int vec_valid_count = 0;
115  Vec_t x, y, z;
116 
117  // set to zero to avoid problems with vectors with less than
118  // VECSIZE valid entries
119  x.setZero();
120  y.setZero();
121  z.setZero();
122  for (size_t n = neighbor_start; n < neighbor_end; ++n) {
123  const size_t inp_idx = neighbors_index[n];
124  const int i = vec_valid_count;
125  x(i) = inp_positions[inp_idx * 3 + 0] -
126  out_positions[out_idx * 3 + 0];
127  y(i) = inp_positions[inp_idx * 3 + 1] -
128  out_positions[out_idx * 3 + 1];
129  z(i) = inp_positions[inp_idx * 3 + 2] -
130  out_positions[out_idx * 3 + 2];
131 
132  const TFeat n_importance =
133  (NEIGHBORS_IMPORTANCE ? neighbors_importance[n]
134  : TFeat(1));
135  normalizers(out_col) += TOut(n_importance);
136 
137  for (int ic = 0; ic < in_channels; ++ic)
138  infeat(i, ic) =
139  inp_features[inp_idx * in_channels + ic];
140 
141  TFeat importance(1.0);
142  if (POINT_IMPORTANCE)
143  importance = inp_importance[inp_idx];
144  if (NEIGHBORS_IMPORTANCE) importance *= n_importance;
145 
146  if (POINT_IMPORTANCE || NEIGHBORS_IMPORTANCE) {
147  for (int ic = 0; ic < in_channels; ++ic)
148  infeat(i, ic) *= importance;
149  }
150 
151  ++vec_valid_count;
152  if (vec_valid_count == VECSIZE) {
153  ComputeFilterCoordinates<ALIGN_CORNERS, MAPPING>(
154  x, y, z, filter_size_xyz, inv_extents,
155  offsets_);
156  interpolation.Interpolate(
157  interp_weights, interp_indices, x, y, z,
158  filter_size_xyz, in_channels);
159  for (int k = 0; k < VECSIZE; ++k)
160  for (int j = 0; j < InterpolationVec_t::Size();
161  ++j) {
162  for (int ic = 0; ic < in_channels; ++ic)
163  B(interp_indices(j, k) + ic, out_col) +=
164  TFeat(interp_weights(j, k)) *
165  infeat(k, ic);
166  }
167  vec_valid_count = 0;
168  }
169  }
170  if (vec_valid_count) {
171  ComputeFilterCoordinates<ALIGN_CORNERS, MAPPING>(
172  x, y, z, filter_size_xyz, inv_extents,
173  offsets_);
174  interpolation.Interpolate(interp_weights,
175  interp_indices, x, y, z,
176  filter_size_xyz, in_channels);
177  for (int k = 0; k < vec_valid_count; ++k)
178  for (int j = 0; j < InterpolationVec_t::Size();
179  ++j) {
180  for (int ic = 0; ic < in_channels; ++ic)
181  B(interp_indices(j, k) + ic, out_col) +=
182  TFeat(interp_weights(j, k)) *
183  infeat(k, ic);
184  }
185  }
186 
187  } // out_idx
188 
189  Eigen::Map<const Eigen::Matrix<TFeat, Eigen::Dynamic,
190  Eigen::Dynamic>>
191  A(filter, out_channels,
192  spatial_filter_size * in_channels);
193  Eigen::Map<Eigen::Matrix<TOut, Eigen::Dynamic, Eigen::Dynamic>>
194  C(out_features + (r.begin() * out_channels),
195  out_channels, range_length);
196 
197  C = (A * B).template cast<TOut>();
198  if (normalize) {
199  for (int i = 0; i < range_length; ++i) {
200  if (normalizers(i) != TOut(0))
201  C.col(i) /= normalizers(i);
202  }
203  }
204  });
205 }
206 
281 template <class TFeat, class TOut, class TReal, class TIndex>
282 void CConvComputeFeaturesCPU(TOut* out_features,
283  const std::vector<int>& filter_dims,
284  const TFeat* filter,
285  size_t num_out,
286  const TReal* out_positions,
287  size_t num_inp,
288  const TReal* inp_positions,
289  const TFeat* inp_features,
290  const TFeat* inp_importance,
291  size_t neighbors_index_size,
292  const TIndex* neighbors_index,
293  const TFeat* neighbors_importance,
294  const int64_t* neighbors_row_splits,
295  const TReal* extents,
296  const TReal* offsets,
297  InterpolationMode interpolation,
298  CoordinateMapping coordinate_mapping,
299  bool align_corners,
300  bool individual_extent,
301  bool isotropic_extent,
302  bool normalize) {
303  // Dispatch all template parameter combinations
304  bool has_importance = inp_importance;
305 
306 #define FN_PARAMETERS \
307  out_features, filter_dims, filter, num_out, out_positions, num_inp, \
308  inp_positions, inp_features, inp_importance, neighbors_index_size, \
309  neighbors_index, neighbors_importance, neighbors_row_splits, \
310  extents, offsets, normalize
311 
312 #define CALL_TEMPLATE(INTERPOLATION, MAPPING, ALIGN_CORNERS, \
313  INDIVIDUAL_EXTENT, ISOTROPIC_EXTENT, HAS_IMPORTANCE) \
314  if (INTERPOLATION == interpolation && MAPPING == coordinate_mapping && \
315  ALIGN_CORNERS == align_corners && \
316  INDIVIDUAL_EXTENT == individual_extent && \
317  ISOTROPIC_EXTENT == isotropic_extent && \
318  HAS_IMPORTANCE == has_importance) \
319  _CConvComputeFeaturesCPU<TFeat, TOut, TReal, TIndex, INTERPOLATION, \
320  MAPPING, ALIGN_CORNERS, INDIVIDUAL_EXTENT, \
321  ISOTROPIC_EXTENT, HAS_IMPORTANCE>( \
322  FN_PARAMETERS);
323 
324 #define CALL_TEMPLATE2(INTERPOLATION, MAPPING) \
325  CALL_TEMPLATE(INTERPOLATION, MAPPING, true, true, true, true) \
326  CALL_TEMPLATE(INTERPOLATION, MAPPING, true, true, true, false) \
327  CALL_TEMPLATE(INTERPOLATION, MAPPING, true, true, false, true) \
328  CALL_TEMPLATE(INTERPOLATION, MAPPING, true, true, false, false) \
329  CALL_TEMPLATE(INTERPOLATION, MAPPING, true, false, true, true) \
330  CALL_TEMPLATE(INTERPOLATION, MAPPING, true, false, true, false) \
331  CALL_TEMPLATE(INTERPOLATION, MAPPING, true, false, false, true) \
332  CALL_TEMPLATE(INTERPOLATION, MAPPING, true, false, false, false) \
333  CALL_TEMPLATE(INTERPOLATION, MAPPING, false, true, true, true) \
334  CALL_TEMPLATE(INTERPOLATION, MAPPING, false, true, true, false) \
335  CALL_TEMPLATE(INTERPOLATION, MAPPING, false, true, false, true) \
336  CALL_TEMPLATE(INTERPOLATION, MAPPING, false, true, false, false) \
337  CALL_TEMPLATE(INTERPOLATION, MAPPING, false, false, true, true) \
338  CALL_TEMPLATE(INTERPOLATION, MAPPING, false, false, true, false) \
339  CALL_TEMPLATE(INTERPOLATION, MAPPING, false, false, false, true) \
340  CALL_TEMPLATE(INTERPOLATION, MAPPING, false, false, false, false)
341 
342 #define CALL_TEMPLATE3(INTERPOLATION) \
343  CALL_TEMPLATE2(INTERPOLATION, CoordinateMapping::BALL_TO_CUBE_RADIAL) \
344  CALL_TEMPLATE2(INTERPOLATION, \
345  CoordinateMapping::BALL_TO_CUBE_VOLUME_PRESERVING) \
346  CALL_TEMPLATE2(INTERPOLATION, CoordinateMapping::IDENTITY)
347 
348 #define CALL_TEMPLATE4 \
349  CALL_TEMPLATE3(InterpolationMode::LINEAR) \
350  CALL_TEMPLATE3(InterpolationMode::LINEAR_BORDER) \
351  CALL_TEMPLATE3(InterpolationMode::NEAREST_NEIGHBOR)
352 
354 
355 #undef CALL_TEMPLATE
356 #undef CALL_TEMPLATE2
357 #undef CALL_TEMPLATE3
358 #undef CALL_TEMPLATE4
359 
360 #undef FN_PARAMETERS
361 }
362 
363 } // namespace impl
364 } // namespace ml
365 } // namespace open3d
#define CALL_TEMPLATE4
#define VECSIZE
Eigen::Matrix3d B
Definition: PointCloudPlanarPatchDetection.cpp:519
InterpolationMode
Definition: ContinuousConvTypes.h:18
void _CConvComputeFeaturesCPU(TOut *out_features, const std::vector< int > &filter_dims, const TFeat *filter, size_t num_out, const TReal *out_positions, size_t num_inp, const TReal *inp_positions, const TFeat *inp_features, const TFeat *inp_importance, size_t neighbors_index_size, const TIndex *neighbors_index, const TFeat *neighbors_importance, const int64_t *neighbors_row_splits, const TReal *extents, const TReal *offsets, bool normalize)
Definition: ContinuousConv.h:30
void CConvComputeFeaturesCPU(TOut *out_features, const std::vector< int > &filter_dims, const TFeat *filter, size_t num_out, const TReal *out_positions, size_t num_inp, const TReal *inp_positions, const TFeat *inp_features, const TFeat *inp_importance, size_t neighbors_index_size, const TIndex *neighbors_index, const TFeat *neighbors_importance, const int64_t *neighbors_row_splits, const TReal *extents, const TReal *offsets, InterpolationMode interpolation, CoordinateMapping coordinate_mapping, bool align_corners, bool individual_extent, bool isotropic_extent, bool normalize)
Definition: ContinuousConv.h:282
CoordinateMapping
Definition: ContinuousConvTypes.h:26
Definition: PinholeCameraIntrinsic.cpp:16
Class for computing interpolation weights.
Definition: CoordinateTransformation.h:185