13 #include <PinholeCameraTrajectoryIO.h>
19 #include "io/TriangleMeshIO.h"
35 const std::vector<geometry::Image>& images,
36 int number_of_vertical_anchors) {
37 std::vector<ImageWarpingField>
fields;
38 for (
size_t i = 0; i < images.size(); i++) {
39 int width = images[i].width_;
40 int height = images[i].height_;
53 template <
typename VecInTypeDouble,
54 typename VecInTypeInt,
58 std::function<
void(
int, VecInTypeDouble&,
double&, VecInTypeInt&)> f,
62 MatOutType JTJ(6 + nonrigidval, 6 + nonrigidval);
63 VecOutType JTr(6 + nonrigidval);
69 MatOutType JTJ_private(6 + nonrigidval, 6 + nonrigidval);
70 VecOutType JTr_private(6 + nonrigidval);
71 double r2_sum_private = 0.0;
72 JTJ_private.setZero();
73 JTr_private.setZero();
77 #pragma omp for nowait
78 for (
int i = 0; i < iteration_num; i++) {
79 f(i, J_r, r, pattern);
80 for (
auto x = 0; x < J_r.size(); x++) {
81 for (
auto y = 0; y < J_r.size(); y++) {
82 JTJ_private(pattern(x), pattern(y)) += J_r(x) * J_r(y);
85 for (
auto x = 0; x < J_r.size(); x++) {
86 JTr_private(pattern(x)) += r * J_r(x);
88 r2_sum_private += r * r;
90 #pragma omp critical(ComputeJTJandJTrNonRigid)
94 r2_sum += r2_sum_private;
99 r2_sum / (
double)iteration_num, iteration_num);
101 return std::make_tuple(std::move(JTJ), std::move(JTr), r2_sum);
110 const std::vector<double>& proxy_intensity,
115 const Eigen::Matrix4d& intrinsic,
116 const Eigen::Matrix4d& extrinsic,
117 const std::vector<int>& visibility_image_to_vertex,
118 const int image_boundary_margin) {
124 int vid = visibility_image_to_vertex[row];
126 Eigen::Vector4d G = extrinsic * Eigen::Vector4d(V(0), V(1), V(2), 1);
127 Eigen::Vector4d L = intrinsic * G;
128 double u = L(0) / L(2);
129 double v = L(1) / L(2);
133 int ii = (int)(u / anchor_step);
134 int jj = (int)(v / anchor_step);
135 if (ii >= warping_fields.
anchor_w_ - 1 ||
139 double p = (u - ii * anchor_step) / anchor_step;
140 double q = (v - jj * anchor_step) / anchor_step;
141 Eigen::Vector2d grids[4] = {
145 warping_fields.
QueryFlow(ii + 1, jj + 1),
147 Eigen::Vector2d uuvv = (1 - p) * (1 - q) * grids[0] +
148 (1 - p) * (q)*grids[1] + (p) * (1 - q) * grids[2] +
156 double gray, dIdfx, dIdfy;
157 std::tie(valid, gray) = images_gray.
FloatValueAt(uu, vv);
158 std::tie(valid, dIdfx) = images_dx.
FloatValueAt(uu, vv);
159 std::tie(valid, dIdfy) = images_dy.
FloatValueAt(uu, vv);
160 Eigen::Vector2d dIdf(dIdfx, dIdfy);
161 Eigen::Vector2d dfdx =
162 ((grids[2] - grids[0]) * (1 - q) + (grids[3] - grids[1]) * q) /
164 Eigen::Vector2d dfdy =
165 ((grids[1] - grids[0]) * (1 - p) + (grids[3] - grids[2]) * p) /
167 double dIdx = dIdf.dot(dfdx);
168 double dIdy = dIdf.dot(dfdy);
169 double invz = 1. / G(2);
170 double v0 = dIdx * intrinsic(0, 0) * invz;
171 double v1 = dIdy * intrinsic(1, 1) * invz;
172 double v2 = -(v0 * G(0) + v1 * G(1)) * invz;
173 J_r(0) = -G(2) * v1 + G(1) * v2;
174 J_r(1) = G(2) * v0 - G(0) * v2;
175 J_r(2) = -G(1) * v0 + G(0) * v1;
179 J_r(6) = dIdf(0) * (1 - p) * (1 - q);
180 J_r(7) = dIdf(1) * (1 - p) * (1 - q);
181 J_r(8) = dIdf(0) * (1 - p) * (q);
182 J_r(9) = dIdf(1) * (1 - p) * (q);
183 J_r(10) = dIdf(0) * (p) * (1 - q);
184 J_r(11) = dIdf(1) * (p) * (1 - q);
185 J_r(12) = dIdf(0) * (p) * (q);
186 J_r(13) = dIdf(1) * (p) * (q);
193 pattern(6) = 6 + (ii + jj * anchor_w) * 2;
194 pattern(7) = 6 + (ii + jj * anchor_w) * 2 + 1;
195 pattern(8) = 6 + (ii + (jj + 1) * anchor_w) * 2;
196 pattern(9) = 6 + (ii + (jj + 1) * anchor_w) * 2 + 1;
197 pattern(10) = 6 + ((ii + 1) + jj * anchor_w) * 2;
198 pattern(11) = 6 + ((ii + 1) + jj * anchor_w) * 2 + 1;
199 pattern(12) = 6 + ((ii + 1) + (jj + 1) * anchor_w) * 2;
200 pattern(13) = 6 + ((ii + 1) + (jj + 1) * anchor_w) * 2 + 1;
201 r = (gray - proxy_intensity[vid]);
206 const std::vector<geometry::RGBDImage>& images_rgbd,
212 std::vector<ImageWarpingField> warping_fields;
215 std::vector<geometry::Image> images_gray;
216 std::vector<geometry::Image> images_dx;
217 std::vector<geometry::Image> images_dy;
218 std::vector<geometry::Image> images_color;
219 std::vector<geometry::Image> images_depth;
220 std::vector<geometry::Image> images_mask;
221 std::vector<std::vector<int>> visibility_vertex_to_image;
222 std::vector<std::vector<int>> visibility_image_to_vertex;
223 std::vector<ImageWarpingField> warping_fields_init;
228 std::vector<std::string> dirs{
235 for (
const std::string& dir : dirs) {
249 std::tie(images_gray, images_dx, images_dy, images_color, images_depth) =
257 for (
size_t i = 0; i < images_mask.size(); ++i) {
266 std::tie(visibility_vertex_to_image, visibility_image_to_vertex) =
268 opt_mesh, images_depth, images_mask, opt_camera_trajectory,
277 std::vector<double> proxy_intensity;
279 int n_camera = int(opt_camera_trajectory.
parameters_.size());
281 opt_camera_trajectory,
282 visibility_vertex_to_image, proxy_intensity,
286 double residual = 0.0;
287 double residual_reg = 0.0;
288 #pragma omp parallel for schedule(static) \
289 num_threads(utility::EstimateMaxThreads())
290 for (
int c = 0; c < n_camera; c++) {
291 int nonrigidval = warping_fields[c].anchor_w_ *
292 warping_fields[c].anchor_h_ * 2;
295 Eigen::Matrix4d pose;
296 pose = opt_camera_trajectory.
parameters_[c].extrinsic_;
298 auto intrinsic = opt_camera_trajectory.
parameters_[c]
299 .intrinsic_.intrinsic_matrix_;
300 auto extrinsic = opt_camera_trajectory.
parameters_[c].extrinsic_;
301 Eigen::Matrix4d intr = Eigen::Matrix4d::Zero();
302 intr.block<3, 3>(0, 0) = intrinsic;
308 i, J_r, r, pattern, opt_mesh, proxy_intensity,
309 images_gray[c], images_dx[c], images_dy[c],
310 warping_fields[c], intr, extrinsic,
311 visibility_image_to_vertex[c],
317 std::tie(JTJ, JTr, r2) =
319 Eigen::MatrixXd, Eigen::VectorXd>(
320 f_lambda, int(visibility_image_to_vertex[c].
size()),
324 visibility_image_to_vertex[c].size() / n_vertex;
325 for (
int j = 0; j < nonrigidval; j++) {
326 double r = weight * (warping_fields[c].flow_(j) -
327 warping_fields_init[c].flow_(j));
328 JTJ(6 + j, 6 + j) += weight * weight;
329 JTr(6 + j) += weight * r;
340 result_pose <<
result.block(0, 0, 6, 1);
344 for (
int j = 0; j < nonrigidval; j++) {
345 warping_fields[c].flow_(j) +=
result(6 + j);
347 opt_camera_trajectory.
parameters_[c].extrinsic_ = pose;
349 #pragma omp critical(RunNonRigidOptimizer)
352 residual_reg += rr_reg;
358 opt_camera_trajectory,
359 visibility_vertex_to_image, proxy_intensity,
365 opt_camera_trajectory,
366 visibility_vertex_to_image,
377 "/non_rigid/opt_camera_trajectory",
382 for (
size_t i = 0; i < warping_fields.size(); ++i) {
384 "{}/iter_{}_camera_{}.json",
394 opt_camera_trajectory, visibility_vertex_to_image,
filament::Texture::InternalFormat format
std::vector< PCLPointField > fields
Eigen::Vector3d getVertice(size_t index) const
unsigned int getVerticeSize() const
std::vector< PinholeCameraParameters > parameters_
List of PinholeCameraParameters objects.
The Image class stores image with customizable width, height, num of channels and bytes per channel.
bool TestImageBoundary(double u, double v, double inner_margin=0.0) const
Test if coordinate (u, v) is located in the inner_marge of the image.
std::pair< bool, double > FloatValueAt(double u, double v) const
Eigen::Vector2d QueryFlow(int i, int j) const
Eigen::Matrix< double, 6, 1 > Vector6d
Eigen::Matrix< double, 14, 1 > Vector14d
Eigen::Matrix< int, 14, 1 > Vector14i
CLOUDVIEWER_HOST_DEVICE Pair< First, Second > make_pair(const First &_first, const Second &_second)
bool WriteTriangleMesh(const std::string &filename, const ccMesh &mesh, bool write_ascii, bool compressed, bool write_vertex_normals, bool write_vertex_colors, bool write_triangle_uvs, bool print_progress)
bool WriteImage(const std::string &filename, const geometry::Image &image, int quality=kCloudViewerImageIODefaultQuality)
bool WriteImageWarpingField(const std::string &filename, const pipelines::color_map::ImageWarpingField &trajectory)
bool WritePinholeCameraTrajectory(const std::string &filename, const camera::PinholeCameraTrajectory &trajectory)
void SetProxyIntensityForVertex(const ccMesh &mesh, const std::vector< geometry::Image > &images_gray, const utility::optional< std::vector< ImageWarpingField >> &warping_fields, const camera::PinholeCameraTrajectory &camera_trajectory, const std::vector< std::vector< int >> &visibility_vertex_to_image, std::vector< double > &proxy_intensity, int image_boundary_margin)
std::pair< ccMesh, camera::PinholeCameraTrajectory > RunNonRigidOptimizer(const ccMesh &mesh, const std::vector< geometry::RGBDImage > &images_rgbd, const camera::PinholeCameraTrajectory &camera_trajectory, const NonRigidOptimizerOption &option)
std::tuple< std::vector< std::vector< int > >, std::vector< std::vector< int > > > CreateVertexAndImageVisibility(const ccMesh &mesh, const std::vector< geometry::Image > &images_depth, const std::vector< geometry::Image > &images_mask, const camera::PinholeCameraTrajectory &camera_trajectory, double maximum_allowable_depth, double depth_threshold_for_visibility_check)
static std::tuple< MatOutType, VecOutType, double > ComputeJTJandJTrNonRigid(std::function< void(int, VecInTypeDouble &, double &, VecInTypeInt &)> f, int iteration_num, int nonrigidval, bool verbose)
std::tuple< std::vector< geometry::Image >, std::vector< geometry::Image >, std::vector< geometry::Image >, std::vector< geometry::Image >, std::vector< geometry::Image > > CreateUtilImagesFromRGBD(const std::vector< geometry::RGBDImage > &images_rgbd)
std::vector< geometry::Image > CreateDepthBoundaryMasks(const std::vector< geometry::Image > &images_depth, double depth_threshold_for_discontinuity_check, int half_dilation_kernel_size_for_discontinuity_map)
void SetGeometryColorAverage(ccMesh &mesh, const std::vector< geometry::Image > &images_color, const utility::optional< std::vector< ImageWarpingField >> &warping_fields, const camera::PinholeCameraTrajectory &camera_trajectory, const std::vector< std::vector< int >> &visibility_vertex_to_image, int image_boundary_margin, int invisible_vertex_color_knn)
static std::vector< ImageWarpingField > CreateWarpingFields(const std::vector< geometry::Image > &images, int number_of_vertical_anchors)
static void ComputeJacobianAndResidualNonRigid(int row, Eigen::Vector14d &J_r, double &r, Eigen::Vector14i &pattern, const ccMesh &mesh, const std::vector< double > &proxy_intensity, const geometry::Image &images_gray, const geometry::Image &images_dx, const geometry::Image &images_dy, const ImageWarpingField &warping_fields, const Eigen::Matrix4d &intrinsic, const Eigen::Matrix4d &extrinsic, const std::vector< int > &visibility_image_to_vertex, const int image_boundary_margin)
bool MakeDirectoryHierarchy(const std::string &directory)
bool DirectoryExists(const std::string &directory)
std::tuple< bool, Eigen::VectorXd > SolveLinearSystemPSD(const Eigen::MatrixXd &A, const Eigen::VectorXd &b, bool prefer_sparse=false, bool check_symmetric=false, bool check_det=false, bool check_psd=false)
Function to solve Ax=b.
Eigen::Matrix4d TransformVector6dToMatrix4d(const Eigen::Vector6d &input)
Generic file read and write utility for python interface.
double maximum_allowable_depth_
double non_rigid_anchor_point_weight_
int number_of_vertical_anchors_
double depth_threshold_for_discontinuity_check_
int maximum_iteration_
Number of iterations for optimization steps.
int half_dilation_kernel_size_for_discontinuity_map_
int image_boundary_margin_
int invisible_vertex_color_knn_
double depth_threshold_for_visibility_check_
std::string debug_output_dir_