17 #include <unordered_map>
23 namespace integration {
30 const Eigen::Vector3d &origin )
34 resolution_(resolution),
35 voxel_num_(resolution * resolution * resolution) {
46 const Eigen::Matrix4d &extrinsic) {
50 if ((
image.depth_.num_of_channels_ != 1) ||
51 (
image.depth_.bytes_per_channel_ != 4) ||
53 image.color_.num_of_channels_ != 3) ||
55 image.color_.bytes_per_channel_ != 1) ||
57 image.color_.num_of_channels_ != 1) ||
59 image.color_.bytes_per_channel_ != 4)) {
61 "[UniformTSDFVolume::Integrate] Unsupported image format.");
66 "[UniformTSDFVolume::Integrate] depth image size is ({} x {}), "
67 "but got ({} x {}) from intrinsic.",
75 "[UniformTSDFVolume::Integrate] color image size is ({} x {}), "
76 "but got ({} x {}) from intrinsic.",
81 auto depth2cameradistance =
85 *depth2cameradistance);
89 auto pointcloud = std::make_shared<ccPointCloud>();
99 if (!(w0 != 0.0f && f0 < 0.98f && f0 >= -0.98f)) {
105 for (
int i = 0; i < 3; i++) {
106 Eigen::Vector3d p1 = p0;
113 const Eigen::Vector3d &c1 =
115 if (w1 != 0.0f && f1 < 0.98f && f1 >= -0.98f &&
119 Eigen::Vector3d p = p0;
120 p(i) = (p0(i) * r1 + p1(i) * r0) / (r0 + r1);
121 pointcloud->addEigenPoint(p +
origin_);
122 if (!pointcloud->hasColors()) {
123 if (!pointcloud->reserveTheRGBTable()) {
128 pointcloud->addEigenColor(
129 ((c0 * r1 + c1 * r0) / (r0 + r1) /
134 pointcloud->addEigenColor(
135 ((c0 * r1 + c1 * r0) / (r0 + r1))
139 if (!pointcloud->hasNormals() &&
140 !pointcloud->reserveTheNormsTable()) {
143 pointcloud->addEigenNorm(GetNormalAt(p));
158 assert(baseVertices);
162 auto mesh = std::make_shared<ccMesh>(baseVertices);
163 mesh->addChild(baseVertices);
169 std::equal_to<Eigen::Vector4i>,
170 Eigen::aligned_allocator<std::pair<const Eigen::Vector4i, int>>>
171 edgeindex_to_vertexindex;
172 int edge_to_index[12];
183 Eigen::Vector3d c[8];
184 for (
int i = 0; i < 8; i++) {
193 cube_index |= (1 << i);
203 if (cube_index == 0 || cube_index == 255) {
206 for (
int i = 0; i < 12; i++) {
207 if (edge_table[cube_index] & (1 << i)) {
210 if (edgeindex_to_vertexindex.find(edge_index) ==
211 edgeindex_to_vertexindex.end()) {
212 edge_to_index[i] = (int)cloud->
size();
213 edgeindex_to_vertexindex[edge_index] =
222 double f0 =
std::abs((
double)f[edge_to_vert[i][0]]);
223 double f1 =
std::abs((
double)f[edge_to_vert[i][1]]);
227 const auto &c0 = c[edge_to_vert[i][0]];
228 const auto &c1 = c[edge_to_vert[i][1]];
239 edgeindex_to_vertexindex.find(edge_index)
244 for (
int i = 0; tri_table[cube_index][i] != -1; i += 3) {
246 edge_to_index[tri_table[cube_index][i]],
247 edge_to_index[tri_table[cube_index][i + 2]],
248 edge_to_index[tri_table[cube_index][i + 1]]));
268 auto voxel = std::make_shared<ccPointCloud>();
280 if (
voxels_[ind].weight_ != 0.0f &&
282 voxels_[ind].tsdf_ >= -0.98f) {
283 voxel->addEigenPoint(pt +
origin_);
284 double c = (
voxels_[ind].tsdf_ + 1.0) * 0.5;
285 if (!voxel->hasColors() && !voxel->reserveTheRGBTable()) {
288 voxel->addEigenColor(Eigen::Vector3d(c, c, c));
298 auto voxel_grid = std::make_shared<geometry::VoxelGrid>();
302 std::vector<std::pair<Eigen::Vector3i, geometry::Voxel>> valid_voxels;
305 #pragma omp parallel for schedule(static) \
306 num_threads(utility::EstimateMaxThreads())
308 #pragma omp parallel for collapse(2) schedule(static) \
309 num_threads(utility::EstimateMaxThreads())
313 std::vector<std::pair<Eigen::Vector3i, geometry::Voxel>>
317 const int ind =
IndexOf(x, y, z);
318 const float w =
voxels_[ind].weight_;
319 const float f =
voxels_[ind].tsdf_;
320 if (w != 0.0f && f < 0.98f && f >= -0.98f) {
321 double c = (f + 1.0) * 0.5;
322 Eigen::Vector3d
color = Eigen::Vector3d(c, c, c);
324 local_voxels.emplace_back(index,
331 valid_voxels.insert(valid_voxels.end(), local_voxels.begin(),
337 for (
const auto &voxel_pair : valid_voxels) {
338 voxel_grid->voxels_[voxel_pair.first] = voxel_pair.second;
345 std::vector<Eigen::Vector2d> sharedvoxels_;
350 #pragma omp parallel for schedule(static) \
351 num_threads(utility::EstimateMaxThreads())
353 #pragma omp parallel for collapse(2) schedule(static) \
354 num_threads(utility::EstimateMaxThreads())
360 const int ind =
IndexOf(x, y, z);
361 const float f =
voxels_[ind].tsdf_;
362 const float w =
voxels_[ind].weight_;
363 sharedvoxels_[ind] = Eigen::Vector2d(f, w);
367 return sharedvoxels_;
371 std::vector<Eigen::Vector3d> sharedcolors_;
375 #pragma omp parallel for schedule(static) \
376 num_threads(utility::EstimateMaxThreads())
378 #pragma omp parallel for collapse(2) schedule(static) \
379 num_threads(utility::EstimateMaxThreads())
385 const int ind =
IndexOf(x, y, z);
386 sharedcolors_[ind] =
voxels_[ind].color_;
390 return sharedcolors_;
394 const std::vector<Eigen::Vector2d> &sharedvoxels) {
397 #pragma omp parallel for schedule(static) \
398 num_threads(utility::EstimateMaxThreads())
400 #pragma omp parallel for collapse(2) schedule(static) \
401 num_threads(utility::EstimateMaxThreads())
407 const int ind =
IndexOf(x, y, z);
408 voxels_[ind].tsdf_ = sharedvoxels[ind](0);
409 voxels_[ind].weight_ = sharedvoxels[ind](1);
416 const std::vector<Eigen::Vector3d> &sharedcolors) {
419 #pragma omp parallel for schedule(static) \
420 num_threads(utility::EstimateMaxThreads())
422 #pragma omp parallel for collapse(2) schedule(static) \
423 num_threads(utility::EstimateMaxThreads())
429 const int ind =
IndexOf(x, y, z);
430 voxels_[ind].color_ = sharedcolors[ind];
439 const Eigen::Matrix4d &extrinsic,
441 const float fx =
static_cast<float>(intrinsic.
GetFocalLength().first);
442 const float fy =
static_cast<float>(intrinsic.
GetFocalLength().second);
445 const Eigen::Matrix4f extrinsic_f = extrinsic.cast<
float>();
446 const float voxel_length_f =
static_cast<float>(
voxel_length_);
447 const float half_voxel_length_f = voxel_length_f * 0.5f;
448 const float sdf_trunc_f =
static_cast<float>(
sdf_trunc_);
449 const float sdf_trunc_inv_f = 1.0f / sdf_trunc_f;
450 const Eigen::Matrix4f extrinsic_scaled_f = extrinsic_f * voxel_length_f;
451 const float safe_width_f = intrinsic.
width_ - 0.0001f;
452 const float safe_height_f = intrinsic.
height_ - 0.0001f;
456 #pragma omp parallel for schedule(static) \
457 num_threads(utility::EstimateMaxThreads())
459 #pragma omp parallel for collapse(2) schedule(static) \
460 num_threads(utility::EstimateMaxThreads())
465 Eigen::Vector4f pt_3d_homo(
float(half_voxel_length_f +
466 voxel_length_f * x +
origin_(0)),
467 float(half_voxel_length_f +
468 voxel_length_f * y +
origin_(1)),
469 float(half_voxel_length_f +
origin_(2)),
471 Eigen::Vector4f pt_camera = extrinsic_f * pt_3d_homo;
473 pt_camera(0) += extrinsic_scaled_f(0, 2),
474 pt_camera(1) += extrinsic_scaled_f(1, 2),
475 pt_camera(2) += extrinsic_scaled_f(2, 2)) {
477 if (pt_camera(2) <= 0) {
481 float u_f = pt_camera(0) * fx / pt_camera(2) + cx + 0.5f;
482 float v_f = pt_camera(1) * fy / pt_camera(2) + cy + 0.5f;
483 if (!(u_f >= 0.0001f && u_f < safe_width_f && v_f >= 0.0001f &&
484 v_f < safe_height_f)) {
490 float d = *
image.depth_.PointerAt<
float>(u, v);
498 (*depth_to_camera_distance_multiplier.
PointerAt<
float>(
500 if (sdf > -sdf_trunc_f) {
502 float tsdf =
std::min(1.0f, sdf * sdf_trunc_inv_f);
506 (
voxels_[v_ind].weight_ + 1.0f);
509 image.color_.PointerAt<uint8_t>(u, v, 0);
510 Eigen::Vector3d rgb_f(rgb[0], rgb[1], rgb[2]);
515 (
voxels_[v_ind].weight_ + 1.0f);
517 const float *intensity =
518 image.color_.PointerAt<
float>(u, v, 0);
520 (
voxels_[v_ind].color_.array() *
523 (
voxels_[v_ind].weight_ + 1.0f);
525 voxels_[v_ind].weight_ += 1.0f;
532 Eigen::Vector3d UniformTSDFVolume::GetNormalAt(
const Eigen::Vector3d &p) {
535 for (
int i = 0; i < 3; i++) {
536 Eigen::Vector3d p0 = p;
538 Eigen::Vector3d p1 = p;
540 n(i) = GetTSDFAt(p1) - GetTSDFAt(p0);
542 return n.normalized();
545 double UniformTSDFVolume::GetTSDFAt(
const Eigen::Vector3d &p) {
547 Eigen::Vector3d p_grid = p /
voxel_length_ - Eigen::Vector3d(0.5, 0.5, 0.5);
548 for (
int i = 0; i < 3; i++) {
551 Eigen::Vector3d r = p_grid - idx.cast<
double>();
554 tsdf += (1 - r(0)) * (1 - r(1)) * (1 - r(2)) *
556 tsdf += (1 - r(0)) * (1 - r(1)) * r(2) *
558 tsdf += (1 - r(0)) * r(1) * (1 - r(2)) *
560 tsdf += (1 - r(0)) * r(1) * r(2) *
562 tsdf += r(0) * (1 - r(1)) * (1 - r(2)) *
564 tsdf += r(0) * (1 - r(1)) * r(2) *
566 tsdf += r(0) * r(1) * (1 - r(2)) *
568 tsdf += r(0) * r(1) * r(2) *
std::shared_ptr< core::Tensor > image
Array of compressed 3D normals (single index)
static ccPointCloud * ToPointCloud(ccHObject *obj, bool *isLockedVertices=nullptr)
Converts current object to 'equivalent' ccPointCloud.
virtual void setLocked(bool state)
Sets the "enabled" property.
virtual void setEnabled(bool state)
Sets the "enabled" property.
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
void addEigenColor(const Eigen::Vector3d &color)
bool reserveTheRGBTable()
Reserves memory to store the RGB colors.
bool hasColors() const override
Returns whether colors are enabled or not.
void shrinkToFit()
Removes unused capacity.
void addEigenPoint(const Eigen::Vector3d &point)
unsigned size() const override
Contains the pinhole camera intrinsic parameters.
int height_
Height of the image.
int width_
Width of the image.
std::pair< double, double > GetFocalLength() const
Returns the focal length in a tuple of X-axis and Y-axis focal lengths.
std::pair< double, double > GetPrincipalPoint() const
The Image class stores image with customizable width, height, num of channels and bytes per channel.
static std::shared_ptr< Image > CreateDepthToCameraDistanceMultiplierFloatImage(const camera::PinholeCameraIntrinsic &intrinsic)
T * PointerAt(int u, int v) const
Function to access the raw data of a single-channel Image.
RGBDImage is for a pair of registered color and depth images,.
Base Voxel class, containing grid id and color.
Base class of the Truncated Signed Distance Function (TSDF) volume.
double sdf_trunc_
Truncation value for signed distance function (SDF).
double voxel_length_
Length of the voxel in meters.
TSDFVolumeColorType color_type_
Color type of the TSDF volume.
__host__ __device__ float length(float2 v)
__host__ __device__ float2 fabs(float2 v)
__host__ __device__ int2 abs(int2 v)
Helper functions for the ml ops.
@ Gray32
32 bit GrayScale.
MiniVec< float, N > floor(const MiniVec< float, N > &a)
Generic file read and write utility for python interface.
Eigen::Matrix< Index, 3, 1 > Vector3i
Eigen::Matrix< Index, 4, 1 > Vector4i