ISAAC  0.2.11
Flight software for the ISAAC project, adding functionality to the Astrobee robot, operating inside the International Space Station.
All Classes Functions Variables Pages
texture_processing.h
1 /* Copyright (c) 2021, United States Government, as represented by the
2  * Administrator of the National Aeronautics and Space Administration.
3  *
4  * All rights reserved.
5  *
6  * The "ISAAC - Integrated System for Autonomous and Adaptive Caretaking
7  * platform" software is licensed under the Apache License, Version 2.0
8  * (the "License"); you may not use this file except in compliance with the
9  * License. You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16  * License for the specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #ifndef TEXTURE_PROCESSING_H_
21 #define TEXTURE_PROCESSING_H_
22 
23 // Here we store some utilities adapted from mvs-texturing, at
24 // https://github.com/nmoehrle/mvs-texturing which were adapted for
25 // use with ISAAC. That software was released under the BSD license.
26 
27 #include <Eigen/Geometry>
28 #include <Eigen/Core>
29 
30 // texrecon includes
31 #include <mve/mesh_io_ply.h>
32 #include <mve/mesh_info.h>
33 #include <mve/mesh.h>
34 #include <mve/image.h>
35 #include <acc/bvh_tree.h>
36 #include <tex/timer.h>
37 #include <tex/texturing.h>
38 #include <tex/tri.h>
39 #include <tex/texture_patch.h>
40 #include <tex/rectangular_bin.h>
41 #include <tex/material_lib.h>
42 #include <util/exception.h>
43 #include <math/vector.h>
44 
45 // OpenCV
46 #include <opencv2/highgui/highgui.hpp>
47 
48 // Astrobee and isaac
49 #include <camera/camera_model.h>
50 #include <dense_map_utils.h>
51 
52 #include <vector>
53 #include <map>
54 #include <limits>
55 #include <string>
56 
57 typedef acc::BVHTree<unsigned int, math::Vec3f> BVHTree;
58 
59 namespace dense_map {
60 
61 // In order to sample a face it is easier to first rotate it so it
62 // is in a plane so that the face normal points along the positive
63 // x axis. All points in the transformed face will have a constant
64 // x. Store the that value of x and together with the
65 // lower-left value of the bounding box in that plane (so min_y, and min_z),
66 // and the number of samples needed (with given pixel size) to
67 // sample that face (with a small padding on both sides).
68 // Also store the transform from that plane to the face itself.
69 
70 // We use 'int64_t' values instead of 'int', as the latter is 32-bit and
71 // the area of some images we encounter can then overflow.
72 
73 struct FaceInfo {
74  double x, min_y, min_z;
75 
76  // We will have [min_y, min_y + width * pixel_size] x [min_z, min_z + height * pixel_size]
77  // contain the face transformed in that plane with the normal pointing along the z axis.
78  int64_t width, height;
79 
80  // The padding to apply to each face bounding box before sampling it
81  int64_t face_info_padding;
82 
83  // The pixel at (x, min_y, min_z) in the plane will end up at location (shift_u, shift_v)
84  // in the texture.
85  int64_t shift_u, shift_v;
86 
87  // Used to flag a valid face
88  bool valid;
89 
90  // The transform which makes a version of the face in the y-z plane to the actual triangle
91  Eigen::Affine3d YZPlaneToTriangleFace;
92 
93  // The vertices of a face after being transformed to a plane with x constant
94  std::vector<Eigen::Vector3d> TransformedVertices;
95 
96  // Initialize all members. Invalid or unprocessed faces will have
97  // shift_u == invalid_shift_u.
98  FaceInfo() {
99  x = 0.0;
100  min_y = 0.0;
101  min_z = 0.0;
102  width = 0L;
103  height = 0L;
104  face_info_padding = 1L;
105  valid = true;
106  shift_u = std::numeric_limits<int>::max();
107  shift_v = 0L;
108  YZPlaneToTriangleFace = Eigen::Affine3d::Identity();
109  TransformedVertices.resize(3);
110  }
111 };
112 
113 // Small utilities
114 Eigen::Vector3d vec3f_to_eigen(math::Vec3f const& v);
115 math::Vec3f eigen_to_vec3f(Eigen::Vector3d const& V);
116 
117 // A texture patch without holding a buffer to the texture but only vertex and face info
119  public:
120  typedef std::shared_ptr<IsaacTexturePatch> Ptr;
121  typedef std::shared_ptr<const IsaacTexturePatch> ConstPtr;
122  typedef std::vector<std::size_t> Faces;
123  typedef std::vector<Eigen::Vector2d> Texcoords;
124 
125  private:
126  int64_t label;
127  Faces faces;
128  Texcoords texcoords;
129  int64_t width, height;
130 
131  public:
133  IsaacTexturePatch(int64_t label, std::vector<std::size_t> const& faces,
134  std::vector<Eigen::Vector2d> const& texcoords,
135  int64_t width, int64_t height);
136 
137  IsaacTexturePatch(IsaacTexturePatch const& texture_patch);
138 
139  static IsaacTexturePatch::Ptr create(IsaacTexturePatch::ConstPtr texture_patch);
140  static IsaacTexturePatch::Ptr create(int64_t label, std::vector<std::size_t> const& faces,
141  std::vector<Eigen::Vector2d> const& texcoords,
142  int64_t width, int64_t height);
143 
144  IsaacTexturePatch::Ptr duplicate(void);
145 
146  std::vector<std::size_t>& get_faces(void);
147  std::vector<std::size_t> const& get_faces(void) const;
148  std::vector<Eigen::Vector2d> & get_texcoords(void);
149  std::vector<Eigen::Vector2d> const& get_texcoords(void) const;
150 
151  int64_t get_label(void) const;
152  int64_t get_width(void) const;
153  int64_t get_height(void) const;
154  int64_t get_size(void) const;
155 };
156 
157 inline IsaacTexturePatch::IsaacTexturePatch(int64_t label, std::vector<std::size_t> const& faces,
158  std::vector<Eigen::Vector2d> const& texcoords,
159  int64_t width, int64_t height)
160  : label(label), faces(faces), texcoords(texcoords), width(width), height(height) {}
161 
162 inline IsaacTexturePatch::IsaacTexturePatch(IsaacTexturePatch const& texture_patch) {
163  label = texture_patch.label;
164  faces = std::vector<std::size_t>(texture_patch.faces);
165  texcoords = std::vector<Eigen::Vector2d>(texture_patch.texcoords);
166  width = texture_patch.width;
167  height = texture_patch.height;
168 }
169 
170 inline IsaacTexturePatch::Ptr IsaacTexturePatch::create(IsaacTexturePatch::ConstPtr texture_patch) {
171  return std::make_shared<IsaacTexturePatch>(*texture_patch);
172 }
173 
174 inline IsaacTexturePatch::Ptr IsaacTexturePatch::create(
175  int64_t label, std::vector<std::size_t> const& faces,
176  std::vector<Eigen::Vector2d> const& texcoords, int64_t width, int64_t height) {
177  return std::make_shared<IsaacTexturePatch>(label, faces, texcoords, width, height);
178 }
179 
180 inline IsaacTexturePatch::Ptr IsaacTexturePatch::duplicate(void) {
181  return Ptr(new IsaacTexturePatch(*this));
182 }
183 
184 inline int64_t IsaacTexturePatch::get_label(void) const { return label; }
185 
186 inline int64_t IsaacTexturePatch::get_width(void) const { return width; }
187 
188 inline int64_t IsaacTexturePatch::get_height(void) const { return height; }
189 
190 inline std::vector<Eigen::Vector2d>& IsaacTexturePatch::get_texcoords(void) {
191  return texcoords;
192 }
193 
194 inline std::vector<std::size_t>& IsaacTexturePatch::get_faces(void) { return faces; }
195 
196 inline std::vector<Eigen::Vector2d> const& IsaacTexturePatch::get_texcoords(void) const {
197  return texcoords;
198 }
199 
200 inline std::vector<std::size_t> const& IsaacTexturePatch::get_faces(void) const { return faces; }
201 
202 inline int64_t IsaacTexturePatch::get_size(void) const { return get_width() * get_height(); }
203 
209  public:
210  typedef std::shared_ptr<IsaacTextureAtlas> Ptr;
211 
212  typedef std::vector<std::size_t> Faces;
213  typedef std::vector<std::size_t> TexcoordIds;
214  typedef std::vector<Eigen::Vector2d> Texcoords;
215 
216  int64_t get_width();
217  int64_t get_height();
218 
219  private:
220  int64_t width, height, determined_height;
221  bool finalized;
222 
223  Faces faces;
224  Texcoords texcoords;
225  TexcoordIds texcoord_ids;
226 
227  mve::ByteImage::Ptr image;
228 
229  RectangularBin::Ptr bin;
230 
231  void resize_atlas(void);
232 
233  public:
234  IsaacTextureAtlas(int64_t width, int64_t height);
235 
236  static IsaacTextureAtlas::Ptr create(int64_t width, int64_t height);
237 
238  Faces& get_faces(void);
239  TexcoordIds& get_texcoord_ids(void);
240  Texcoords& get_texcoords(void);
241  mve::ByteImage::Ptr& get_image(void);
242 
243  bool insert(IsaacTexturePatch::ConstPtr texture_patch);
244 
245  void scale_texcoords(void);
246 
247  void merge_texcoords(void);
248 
249  void finalize(void);
250 };
251 
252 inline IsaacTextureAtlas::Ptr IsaacTextureAtlas::create(int64_t width, int64_t height) {
253  return Ptr(new IsaacTextureAtlas(width, height));
254 }
255 
256 inline IsaacTextureAtlas::Faces& IsaacTextureAtlas::get_faces(void) { return faces; }
257 
258 inline IsaacTextureAtlas::TexcoordIds& IsaacTextureAtlas::get_texcoord_ids(void) {
259  return texcoord_ids;
260 }
261 
262 inline IsaacTextureAtlas::Texcoords& IsaacTextureAtlas::get_texcoords(void) { return texcoords; }
263 
264 inline mve::ByteImage::Ptr& IsaacTextureAtlas::get_image(void) { return image; }
265 
266 inline int64_t IsaacTextureAtlas::get_width() { return width; }
267 
268 inline int64_t IsaacTextureAtlas::get_height() { return height; }
269 
270 
276  public:
277  struct Face {
278  std::size_t vertex_ids[3];
279  std::size_t texcoord_ids[3];
280  std::size_t normal_ids[3];
281  };
282 
283  struct Group {
284  std::string material_name;
285  std::vector<Face> faces;
286  };
287 
288  typedef std::vector<math::Vec3f> Vertices;
289  typedef std::vector<Eigen::Vector2d> TexCoords;
290  typedef std::vector<math::Vec3f> Normals;
291  typedef std::vector<Group> Groups;
292 
293  private:
294  Vertices vertices;
295  TexCoords texcoords;
296  Normals normals;
297  Groups groups;
298  MaterialLib material_lib;
299 
300  public:
303  void save_to_files(std::string const & prefix) const;
304 
305  MaterialLib & get_material_lib(void);
306  Vertices & get_vertices(void);
307  TexCoords & get_texcoords(void);
308  Normals & get_normals(void);
309  Groups & get_groups(void);
310 
311  static void save(IsaacObjModel const & model, std::string const & prefix);
312 };
313 
314 inline
315 MaterialLib &
316 IsaacObjModel::get_material_lib(void) {
317  return material_lib;
318 }
319 
320 inline
321 IsaacObjModel::Vertices &
322 IsaacObjModel::get_vertices(void) {
323  return vertices;
324 }
325 
326 inline
327 IsaacObjModel::TexCoords &
328 IsaacObjModel::get_texcoords(void) {
329  return texcoords;
330 }
331 
332 inline
333 IsaacObjModel::Normals &
334 IsaacObjModel::get_normals(void) {
335  return normals;
336 }
337 
338 inline
339 IsaacObjModel::Groups &
340 IsaacObjModel::get_groups(void) {
341  return groups;
342 }
343 
344 // Load and prepare a mesh
345 void loadMeshBuildTree(std::string const& mesh_file, mve::TriangleMesh::Ptr& mesh,
346  std::shared_ptr<mve::MeshInfo>& mesh_info,
347  std::shared_ptr<tex::Graph>& graph,
348  std::shared_ptr<BVHTree>& bvh_tree);
349 
350 void formModel(mve::TriangleMesh::ConstPtr mesh, double pixel_size, int64_t num_threads,
351  // outputs
352  std::vector<FaceInfo>& face_projection_info,
353  std::vector<IsaacTextureAtlas::Ptr>& texture_atlases,
354  IsaacObjModel& model);
355 
356 // Put an textured mesh obj file in a string
357 void formObj(IsaacObjModel& texture_model, std::string const& out_prefix, std::string& obj_str);
358 
359 // Put an textured mesh obj file in a string
360 void formObjCustomUV(mve::TriangleMesh::ConstPtr mesh, std::vector<Eigen::Vector3i> const& face_vec,
361  std::map<int, Eigen::Vector2d> const& uv_map,
362  std::string const& out_prefix, std::string& obj_str);
363 
364 void formMtl(std::string const& out_prefix, std::string& mtl_str);
365 
366 // The images from the bag may need to be resized to be the same
367 // size as in the calibration file.
368 void adjustImageSize(camera::CameraParameters const& cam_params, cv::Mat & image);
369 
370 // Project texture and find the UV coordinates
371 void projectTexture(mve::TriangleMesh::ConstPtr mesh, std::shared_ptr<BVHTree> bvh_tree,
372  cv::Mat const& image, camera::CameraModel const& cam,
373  double num_exclude_boundary_pixels,
374  // outputs
375  std::vector<double>& smallest_cost_per_face,
376  std::vector<Eigen::Vector3i>& face_vec,
377  std::map<int, Eigen::Vector2d>& uv_map);
378 
379 // Project texture on a texture model that was pre-filled already, so
380 // only the texture pixel values need to be computed
381 void projectTexture(mve::TriangleMesh::ConstPtr mesh, std::shared_ptr<BVHTree> bvh_tree,
382  cv::Mat const& image, camera::CameraModel const& cam,
383  std::vector<double>& smallest_cost_per_face, double pixel_size,
384  int64_t num_threads, std::vector<FaceInfo> const& face_projection_info,
385  std::vector<IsaacTextureAtlas::Ptr>& texture_atlases,
386  IsaacObjModel& model, cv::Mat& out_texture);
387 
388 // Find where ray emanating from a distorted pixel intersects a mesh. Return true
389 // on success.
390 bool ray_mesh_intersect(Eigen::Vector2d const& dist_pix,
391  camera::CameraParameters const& cam_params,
392  Eigen::Affine3d const& world_to_cam,
393  mve::TriangleMesh::Ptr const& mesh,
394  std::shared_ptr<BVHTree> const& bvh_tree,
395  double min_ray_dist, double max_ray_dist,
396  // Output
397  Eigen::Vector3d& intersection);
398 
399 void meshProject(mve::TriangleMesh::Ptr const& mesh, std::shared_ptr<BVHTree> const& bvh_tree,
400  cv::Mat const& image,
401  Eigen::Affine3d const& world_to_cam, camera::CameraParameters const& cam_params,
402  int64_t num_exclude_boundary_pixels, std::string const& out_prefix);
403 
404 // Save a model
405 void isaac_save_model(IsaacObjModel* obj_model, std::string const& prefix);
406 
407 } // namespace dense_map
408 
409 #endif // TEXTURE_PROCESSING_H_
dense_map::IsaacObjModel::save_to_files
void save_to_files(std::string const &prefix) const
dense_map::IsaacObjModel::Face
Definition: texture_processing.h:277
dense_map::IsaacObjModel
Definition: texture_processing.h:275
dense_map::IsaacTexturePatch
Definition: texture_processing.h:118
dense_map::IsaacObjModel::Group
Definition: texture_processing.h:283
dense_map::IsaacTexturePatch::IsaacTexturePatch
IsaacTexturePatch(int64_t label, std::vector< std::size_t > const &faces, std::vector< Eigen::Vector2d > const &texcoords, int64_t width, int64_t height)
Definition: texture_processing.h:157
dense_map::IsaacTextureAtlas
Definition: texture_processing.h:208
dense_map::FaceInfo
Definition: texture_processing.h:73