ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
texturing.h
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 
8 #pragma once
9 
10 #include <Eigen/Core>
11 #include <QImage>
12 #include <map>
13 #include <memory>
14 #include <string>
15 #include <vector>
16 
17 #include "util/types.h"
18 
19 // Forward declarations for CloudViewer types
20 class ccMesh;
21 
22 namespace cloudViewer {
23 namespace camera {
24 class PinholeCameraTrajectory;
25 }
26 } // namespace cloudViewer
27 
28 namespace colmap {
29 class Image;
30 class Camera;
31 class Reconstruction;
32 
33 namespace mvs {
34 class Workspace;
35 
36 // Camera view for texturing
37 struct TextureView {
38  std::size_t id;
39  std::string image_file;
40  int width;
41  int height;
42  Eigen::Matrix3f projection;
43  Eigen::Matrix4f world_to_cam;
44  Eigen::Vector3f pos;
45  Eigen::Vector3f viewdir;
46 
47  // Image data (loaded on demand)
48  mutable std::shared_ptr<QImage> image_data;
49 
50  TextureView(std::size_t id,
51  const std::string& image_file,
52  const Eigen::Matrix3f& projection,
53  const Eigen::Matrix4f& world_to_cam,
54  const Eigen::Vector3f& pos,
55  const Eigen::Vector3f& viewdir,
56  int width,
57  int height);
58 
59  // Project 3D point to 2D pixel coordinates
60  Eigen::Vector2f GetPixelCoords(const Eigen::Vector3f& vertex) const;
61 
62  // Check if pixel is within image bounds
63  bool ValidPixel(const Eigen::Vector2f& pixel) const;
64 
65  // Check if triangle is inside view frustum
66  bool Inside(const Eigen::Vector3f& v1,
67  const Eigen::Vector3f& v2,
68  const Eigen::Vector3f& v3) const;
69 };
70 
71 // Texture patch (atlas region)
72 struct TexturePatch {
73  int label;
74  std::vector<size_t> faces;
75  std::vector<Eigen::Vector2f> texcoords;
76  std::shared_ptr<QImage> image;
78 
79  TexturePatch(int label,
80  const std::vector<size_t>& faces,
81  const std::vector<Eigen::Vector2f>& texcoords,
82  std::shared_ptr<QImage> image,
83  int min_x,
84  int min_y,
85  int max_x,
86  int max_y);
87 };
88 
89 // MVS-based texture mapping implementation
90 // Based on the mvs-texturing approach with depth/normal map guidance
91 class MvsTexturing {
92 public:
93  struct Options {
94  bool verbose = true;
95  float max_depth_error = 0.01f;
97  75.0f; // Maximum viewing angle in degrees
98  bool use_depth_normal_maps = true; // For visibility testing
99  bool use_gradient_magnitude = true; // Use GMI for quality
100  };
101 
102  MvsTexturing(const Options& options,
103  const Reconstruction& reconstruction,
104  Workspace* workspace,
105  const std::string& image_path);
106 
107  // Main texturing function
108  // Uses ccMesh from CloudViewer
109  bool TextureMesh(ccMesh& mesh,
110  const ::cloudViewer::camera::PinholeCameraTrajectory&
111  camera_trajectory,
112  const std::string& output_path);
113 
114 private:
115  // Create texture views from camera trajectory
116  void CreateTextureViews(
117  const ::cloudViewer::camera::PinholeCameraTrajectory&
118  camera_trajectory);
119 
120  // Calculate data costs for each face-view combination
121  void CalculateDataCosts(const ccMesh& mesh);
122 
123  // View selection using graph cut
124  void SelectViews();
125 
126  // Generate texture patches
127  void GenerateTexturePatches(const ccMesh& mesh);
128 
129  // Seam leveling
130  void SeamLeveling(const ccMesh& mesh);
131 
132  // Generate texture atlases
133  void GenerateTextureAtlases();
134 
135  // Build and save OBJ model
136  bool SaveOBJModel(const std::string& output_path, const ccMesh& mesh);
137 
138  // Helper methods for visibility and quality testing
139  int GetWorkspaceImageIdx(const image_t image_id) const;
140  bool IsPointVisible(const Eigen::Vector3d& point3d,
141  const colmap::Image& image,
142  const colmap::Camera& camera,
143  int workspace_image_idx) const;
144 
145  // GMI (Gradient Magnitude Image) methods
146  QImage ComputeGradientMagnitudeImage(const QImage& image);
147  float CalculateGMIQuality(size_t view_id,
148  const Eigen::Vector2f& p1,
149  const Eigen::Vector2f& p2,
150  const Eigen::Vector2f& p3);
151  bool IsPointInTriangle(float px,
152  float py,
153  const Eigen::Vector2f& p1,
154  const Eigen::Vector2f& p2,
155  const Eigen::Vector2f& p3) const;
156 
157  Options options_;
158  const Reconstruction& reconstruction_;
159  Workspace* workspace_;
160  const std::string image_path_;
161 
162  std::vector<std::unique_ptr<TextureView>> texture_views_;
163  std::vector<std::unique_ptr<TexturePatch>> texture_patches_;
164 
165  // Texture atlases
166  struct TextureAtlas {
167  unsigned int width;
168  unsigned int height;
169  std::shared_ptr<QImage> image;
170  std::vector<size_t> face_ids;
171  std::vector<Eigen::Vector2f> texcoords;
172  std::vector<size_t> texcoord_ids;
173  };
174  std::vector<TextureAtlas> texture_atlases_;
175 
176  // Mapping from view_id to image_id
177  std::vector<image_t> view_to_image_id_;
178 
179  // GMI (Gradient Magnitude Images) for each texture view
180  mutable std::vector<QImage> gradient_magnitude_images_;
181 
182  // Helper methods for graph operations
183  void BuildAdjacencyGraph(const ccMesh& mesh);
184  float ComputePairwiseCost(size_t face1,
185  size_t face2,
186  size_t view1,
187  size_t view2) const;
188 
189  // Data structures for texturing
190  struct FaceProjectionInfo {
191  size_t view_id;
192  float quality;
193  Eigen::Vector3f mean_color;
194  };
195  std::vector<std::vector<FaceProjectionInfo>> face_projection_infos_;
196  std::vector<size_t> face_labels_;
197 
198  // Vertex projection info
199  struct VertexProjectionInfo {
200  size_t texture_patch_id;
201  Eigen::Vector2f projection;
202  std::vector<size_t> faces;
203 
204  bool operator<(const VertexProjectionInfo& other) const {
205  return texture_patch_id < other.texture_patch_id;
206  }
207  };
208  std::vector<std::vector<VertexProjectionInfo>> vertex_projection_infos_;
209 
210  // Adjacency graph for mesh faces
211  std::vector<std::vector<size_t>> face_adjacency_;
212 
213  // Data costs for graph cut
214  std::vector<std::vector<std::pair<size_t, float>>> data_costs_;
215 
216  // Seam edges
217  struct SeamEdge {
218  size_t v1, v2;
219  size_t face1, face2;
220  };
221  std::vector<SeamEdge> seam_edges_;
222 
223  // Helper methods
224  void GetSubgraphs(size_t label,
225  std::vector<std::vector<size_t>>* subgraphs) const;
226  void MergeVertexProjectionInfos();
227 };
228 
229 } // namespace mvs
230 } // namespace colmap
std::shared_ptr< core::Tensor > image
int width
int height
Triangular mesh.
Definition: ecvMesh.h:35
MvsTexturing(const Options &options, const Reconstruction &reconstruction, Workspace *workspace, const std::string &image_path)
Definition: texturing.cc:131
bool TextureMesh(ccMesh &mesh, const ::cloudViewer::camera::PinholeCameraTrajectory &camera_trajectory, const std::string &output_path)
Definition: texturing.cc:236
constexpr bool operator<(const optional< T > &x, const optional< T > &y)
Definition: Optional.h:625
Generic file read and write utility for python interface.
uint32_t image_t
Definition: types.h:61
std::vector< Eigen::Vector2f > texcoords
Definition: texturing.h:75
std::shared_ptr< QImage > image
Definition: texturing.h:76
std::vector< size_t > faces
Definition: texturing.h:74
TexturePatch(int label, const std::vector< size_t > &faces, const std::vector< Eigen::Vector2f > &texcoords, std::shared_ptr< QImage > image, int min_x, int min_y, int max_x, int max_y)
Definition: texturing.cc:114
Eigen::Matrix4f world_to_cam
Definition: texturing.h:43
bool ValidPixel(const Eigen::Vector2f &pixel) const
Definition: texturing.cc:100
bool Inside(const Eigen::Vector3f &v1, const Eigen::Vector3f &v2, const Eigen::Vector3f &v3) const
Definition: texturing.cc:105
TextureView(std::size_t id, const std::string &image_file, const Eigen::Matrix3f &projection, const Eigen::Matrix4f &world_to_cam, const Eigen::Vector3f &pos, const Eigen::Vector3f &viewdir, int width, int height)
Definition: texturing.cc:54
Eigen::Vector2f GetPixelCoords(const Eigen::Vector3f &vertex) const
Definition: texturing.cc:71
Eigen::Matrix3f projection
Definition: texturing.h:42
Eigen::Vector3f pos
Definition: texturing.h:44
Eigen::Vector3f viewdir
Definition: texturing.h:45
std::string image_file
Definition: texturing.h:39
std::shared_ptr< QImage > image_data
Definition: texturing.h:48