ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
color_map.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
9 
10 #include <Logging.h>
11 #include <RGBDImage.h>
12 #include <ecvMesh.h>
13 
17 #include "pybind/docstring.h"
18 
19 namespace cloudViewer {
20 namespace pipelines {
21 namespace color_map {
22 
23 void pybind_color_map_options(py::module &m) {
24  static std::unordered_map<std::string, std::string> colormap_docstrings = {
25  {"non_rigid_camera_coordinate",
26  "bool: (Default ``False``) Set to ``True`` to enable non-rigid "
27  "optimization (optimizing camera extrinsic params and image "
28  "wrapping field for color assignment), set to ``False`` to only "
29  "enable rigid optimization (optimize camera extrinsic params)."},
30  {"number_of_vertical_anchors",
31  "int: (Default ``16``) Number of vertical anchor points for image "
32  "wrapping field. The number of horizontal anchor points is "
33  "computed automatically based on the number of vertical anchor "
34  "points. This option is only used when non-rigid optimization is "
35  "enabled."},
36  {"non_rigid_anchor_point_weight",
37  "float: (Default ``0.316``) Additional regularization terms added "
38  "to non-rigid regularization. A higher value results gives more "
39  "conservative updates. If the residual error does not stably "
40  "decrease, it is mainly because images are being bended abruptly. "
41  "In this case, consider making iteration more conservative by "
42  "increasing the value. This option is only used when non-rigid "
43  "optimization is enabled."},
44  {"maximum_iteration",
45  "int: (Default ``300``) Number of iterations for optimization "
46  "steps."},
47  {"maximum_allowable_depth",
48  "float: (Default ``2.5``) Parameter to check the visibility of a "
49  "point. Points with depth larger than ``maximum_allowable_depth`` "
50  "in a RGB-D will be marked as invisible for the camera producing "
51  "that RGB-D image. Select a proper value to include necessary "
52  "points while ignoring unwanted points such as the background."},
53  {"depth_threshold_for_visibility_check",
54  "float: (Default ``0.03``) Parameter for point visibility check. "
55  "When the difference of a point's depth value in the RGB-D image "
56  "and the point's depth value in the 3D mesh is greater than "
57  "``depth_threshold_for_visibility_check``, the point is marked as "
58  "invisible to the camera producing the RGB-D image."},
59  {"depth_threshold_for_discontinuity_check",
60  "float: (Default ``0.1``) Parameter to check the visibility of a "
61  "point. It's often desirable to ignore points where there is an "
62  "abrupt change in depth value. First the depth gradient image is "
63  "computed, points are considered to be invisible if the depth "
64  "gradient magnitude is larger than "
65  "``depth_threshold_for_discontinuity_check``."},
66  {"half_dilation_kernel_size_for_discontinuity_map",
67  "int: (Default ``3``) Parameter to check the visibility of a "
68  "point. Related to ``depth_threshold_for_discontinuity_check``, "
69  "when boundary points are detected, dilation is performed to "
70  "ignore points near the object boundary. "
71  "``half_dilation_kernel_size_for_discontinuity_map`` specifies "
72  "the half-kernel size for the dilation applied on the visibility "
73  "mask image."},
74  {"image_boundary_margin",
75  "int: (Default ``10``) If a projected 3D point onto a 2D image "
76  "lies in the image border within ``image_boundary_margin``, the "
77  "3D point is considered invisible from the camera producing the "
78  "image. This parmeter is not used for visibility check, but used "
79  "when computing the final color assignment after color map "
80  "optimization."},
81  {"invisible_vertex_color_knn",
82  "int: (Default ``3``) If a vertex is invisible from all images, "
83  "we assign the averaged color of the k nearest visible vertices "
84  "to fill the invisible vertex. Set to ``0`` to disable this "
85  "feature and all invisible vertices will be black."},
86  {"debug_output_dir",
87  "If specified, the intermediate results will be stored in in the "
88  "debug output dir. Existing files will be overwritten if the "
89  "names are the same."}};
90 
91  py::class_<pipelines::color_map::RigidOptimizerOption>
92  rigid_optimizer_option(m, "RigidOptimizerOption",
93  "Rigid optimizer option class.");
94  rigid_optimizer_option.def(
95  py::init([](int maximum_iteration, double maximum_allowable_depth,
96  double depth_threshold_for_visibility_check,
97  double depth_threshold_for_discontinuity_check,
98  int half_dilation_kernel_size_for_discontinuity_map,
99  int image_boundary_margin,
100  int invisible_vertex_color_knn,
101  const std::string &debug_output_dir) {
103  option->maximum_iteration_ = maximum_iteration;
104  option->maximum_allowable_depth_ = maximum_allowable_depth;
105  option->depth_threshold_for_visibility_check_ =
106  depth_threshold_for_visibility_check;
107  option->depth_threshold_for_discontinuity_check_ =
108  depth_threshold_for_discontinuity_check;
109  option->half_dilation_kernel_size_for_discontinuity_map_ =
110  half_dilation_kernel_size_for_discontinuity_map;
111  option->image_boundary_margin_ = image_boundary_margin;
112  option->invisible_vertex_color_knn_ =
113  invisible_vertex_color_knn;
114  option->debug_output_dir_ = debug_output_dir;
115  return option;
116  }),
117  "maximum_iteration"_a = 0, "maximum_allowable_depth"_a = 2.5,
118  "depth_threshold_for_visibility_check"_a = 0.03,
119  "depth_threshold_for_discontinuity_check"_a = 0.1,
120  "half_dilation_kernel_size_for_discontinuity_map"_a = 3,
121  "image_boundary_margin"_a = 10, "invisible_vertex_color_knn"_a = 3,
122  "debug_output_dir"_a = "");
123 
124  docstring::ClassMethodDocInject(m, "RigidOptimizerOption", "__init__",
125  colormap_docstrings);
126 
127  py::class_<pipelines::color_map::NonRigidOptimizerOption>
128  non_rigid_optimizer_option(m, "NonRigidOptimizerOption",
129  "Non Rigid optimizer option class.");
130  non_rigid_optimizer_option.def(
131  py::init([](int number_of_vertical_anchors,
132  double non_rigid_anchor_point_weight,
133  int maximum_iteration, double maximum_allowable_depth,
134  double depth_threshold_for_visibility_check,
135  double depth_threshold_for_discontinuity_check,
136  int half_dilation_kernel_size_for_discontinuity_map,
137  int image_boundary_margin,
138  int invisible_vertex_color_knn,
139  const std::string &debug_output_dir) {
142  number_of_vertical_anchors;
143  option->non_rigid_anchor_point_weight_ =
144  non_rigid_anchor_point_weight;
145  option->maximum_iteration_ = maximum_iteration;
146  option->maximum_allowable_depth_ = maximum_allowable_depth;
147  option->depth_threshold_for_visibility_check_ =
148  depth_threshold_for_visibility_check;
149  option->depth_threshold_for_discontinuity_check_ =
150  depth_threshold_for_discontinuity_check;
151  option->half_dilation_kernel_size_for_discontinuity_map_ =
152  half_dilation_kernel_size_for_discontinuity_map;
153  option->image_boundary_margin_ = image_boundary_margin;
154  option->invisible_vertex_color_knn_ =
155  invisible_vertex_color_knn;
156  option->debug_output_dir_ = debug_output_dir;
157  return option;
158  }),
159  "number_of_vertical_anchors"_a = 16,
160  "non_rigid_anchor_point_weight"_a = 0.316,
161  "maximum_iteration"_a = 0, "maximum_allowable_depth"_a = 2.5,
162  "depth_threshold_for_visibility_check"_a = 0.03,
163  "depth_threshold_for_discontinuity_check"_a = 0.1,
164  "half_dilation_kernel_size_for_discontinuity_map"_a = 3,
165  "image_boundary_margin"_a = 10, "invisible_vertex_color_knn"_a = 3,
166  "debug_output_dir"_a = "");
167 
168  docstring::ClassMethodDocInject(m, "NonRigidOptimizerOption", "__init__",
169  colormap_docstrings);
170 }
171 
172 void pybind_color_map_classes(py::module &m) {
173  m.def("run_rigid_optimizer", &pipelines::color_map::RunRigidOptimizer,
174  "Run rigid optimization.");
175  m.def("run_non_rigid_optimizer",
177  "Run non-rigid optimization.");
178 }
179 
180 void pybind_color_map(py::module &m) {
181  py::module m_submodule =
182  m.def_submodule("color_map", "Color map optimization pipeline");
183  pybind_color_map_options(m_submodule);
184  pybind_color_map_classes(m_submodule);
185 }
186 
187 } // namespace color_map
188 } // namespace pipelines
189 } // namespace cloudViewer
void ClassMethodDocInject(py::module &pybind_module, const std::string &class_name, const std::string &function_name, const std::unordered_map< std::string, std::string > &map_parameter_body_docs)
Definition: docstring.cpp:27
std::pair< ccMesh, camera::PinholeCameraTrajectory > RunRigidOptimizer(const ccMesh &mesh, const std::vector< geometry::RGBDImage > &images_rgbd, const camera::PinholeCameraTrajectory &camera_trajectory, const RigidOptimizerOption &option)
std::pair< ccMesh, camera::PinholeCameraTrajectory > RunNonRigidOptimizer(const ccMesh &mesh, const std::vector< geometry::RGBDImage > &images_rgbd, const camera::PinholeCameraTrajectory &camera_trajectory, const NonRigidOptimizerOption &option)
void pybind_color_map(py::module &m)
Definition: color_map.cpp:180
void pybind_color_map_options(py::module &m)
Definition: color_map.cpp:23
void pybind_color_map_classes(py::module &m)
Definition: color_map.cpp:172
Generic file read and write utility for python interface.
int maximum_iteration_
Number of iterations for optimization steps.