Open3D (C++ API)  0.19.0
Loading...
Searching...
No Matches
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
14namespace open3d {
15namespace ml {
16namespace impl {
17
20template <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>
30void _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
281template <class TFeat, class TOut, class TReal, class TIndex>
282void 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