ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
mvs.cc
Go to the documentation of this file.
1 // Copyright (c) 2018, ETH Zurich and UNC Chapel Hill.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 //
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 //
14 // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of
15 // its contributors may be used to endorse or promote products derived
16 // from this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
22 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 // POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Author: Johannes L. Schoenberger (jsch-at-demuc-dot-de)
31 
32 #include "exe/mvs.h"
33 
34 #include "base/reconstruction.h"
35 #include "mvs/fusion.h"
36 #include "mvs/meshing.h"
37 #include "mvs/patch_match.h"
38 #include "util/misc.h"
39 #include "util/option_manager.h"
40 
41 namespace colmap {
42 
43 int RunDelaunayMesher(int argc, char** argv) {
44 #ifndef CGAL_ENABLED
45  std::cerr << "ERROR: Delaunay meshing requires CGAL, which is not "
46  "available on your system."
47  << std::endl;
48  return EXIT_FAILURE;
49 #else // CGAL_ENABLED
50  std::string input_path;
51  std::string input_type = "dense";
52  std::string output_path;
53 
54  OptionManager options;
55  options.AddRequiredOption(
56  "input_path", &input_path,
57  "Path to either the dense workspace folder or the sparse reconstruction");
58  options.AddDefaultOption("input_type", &input_type, "{dense, sparse}");
59  options.AddRequiredOption("output_path", &output_path);
60  options.AddDelaunayMeshingOptions();
61  options.Parse(argc, argv);
62 
63  StringToLower(&input_type);
64  if (input_type == "sparse") {
65  mvs::SparseDelaunayMeshing(*options.delaunay_meshing, input_path,
66  output_path);
67  } else if (input_type == "dense") {
68  mvs::DenseDelaunayMeshing(*options.delaunay_meshing, input_path,
69  output_path);
70  } else {
71  std::cout << "WARNING: Invalid input type - "
72  "supported values are 'sparse' and 'dense'."
73  << std::endl;
74  return EXIT_FAILURE;
75  }
76 
77  return EXIT_SUCCESS;
78 #endif // CGAL_ENABLED
79 }
80 
81 int RunPatchMatchStereo(int argc, char** argv) {
82 #ifndef CUDA_ENABLED
83  std::cerr << "ERROR: Dense stereo reconstruction requires CUDA, which is not "
84  "available on your system."
85  << std::endl;
86  return EXIT_FAILURE;
87 #else // CUDA_ENABLED
88  std::string workspace_path;
89  std::string workspace_format = "COLMAP";
90  std::string pmvs_option_name = "option-all";
91  std::string config_path;
92 
93  OptionManager options;
94  options.AddRequiredOption(
95  "workspace_path", &workspace_path,
96  "Path to the folder containing the undistorted images");
97  options.AddDefaultOption("workspace_format", &workspace_format,
98  "{COLMAP, PMVS}");
99  options.AddDefaultOption("pmvs_option_name", &pmvs_option_name);
100  options.AddDefaultOption("config_path", &config_path);
101  options.AddPatchMatchStereoOptions();
102  options.Parse(argc, argv);
103 
104  StringToLower(&workspace_format);
105  if (workspace_format != "colmap" && workspace_format != "pmvs") {
106  std::cout << "WARNING: Invalid `workspace_format` - supported values are "
107  "'COLMAP' or 'PMVS'."
108  << std::endl;
109  return EXIT_FAILURE;
110  }
111 
112  mvs::PatchMatchController controller(*options.patch_match_stereo,
113  workspace_path, workspace_format,
114  pmvs_option_name, config_path);
115 
116  controller.Start();
117  controller.Wait();
118 
119  return EXIT_SUCCESS;
120 #endif // CUDA_ENABLED
121 }
122 
123 int RunPoissonMesher(int argc, char** argv) {
124  std::string input_path;
125  std::string output_path;
126 
127  OptionManager options;
128  options.AddRequiredOption("input_path", &input_path);
129  options.AddRequiredOption("output_path", &output_path);
130  options.AddPoissonMeshingOptions();
131  options.Parse(argc, argv);
132 
133  CHECK(mvs::PoissonMeshing(*options.poisson_meshing, input_path, output_path));
134 
135  return EXIT_SUCCESS;
136 }
137 
138 int RunStereoFuser(int argc, char** argv) {
139  std::string workspace_path;
140  std::string input_type = "geometric";
141  std::string workspace_format = "COLMAP";
142  std::string pmvs_option_name = "option-all";
143  std::string output_type = "PLY";
144  std::string output_path;
145  std::string bbox_path;
146 
147  OptionManager options;
148  options.AddRequiredOption("workspace_path", &workspace_path);
149  options.AddDefaultOption("workspace_format", &workspace_format,
150  "{COLMAP, PMVS}");
151  options.AddDefaultOption("pmvs_option_name", &pmvs_option_name);
152  options.AddDefaultOption("input_type", &input_type,
153  "{photometric, geometric}");
154  options.AddDefaultOption("output_type", &output_type, "{BIN, TXT, PLY}");
155  options.AddRequiredOption("output_path", &output_path);
156  options.AddDefaultOption("bbox_path", &bbox_path);
157  options.AddStereoFusionOptions();
158  options.Parse(argc, argv);
159 
160  StringToLower(&workspace_format);
161  if (workspace_format != "colmap" && workspace_format != "pmvs") {
162  std::cout << "WARNING: Invalid `workspace_format` - supported values are "
163  "'COLMAP' or 'PMVS'."
164  << std::endl;
165  return EXIT_FAILURE;
166  }
167 
168  StringToLower(&input_type);
169  if (input_type != "photometric" && input_type != "geometric") {
170  std::cout << "WARNING: Invalid input type - supported values are "
171  "'photometric' and 'geometric'."
172  << std::endl;
173  return EXIT_FAILURE;
174  }
175 
176  if (!bbox_path.empty()) {
177  std::ifstream file(bbox_path);
178  if (file.is_open()) {
179  auto& min_bound = options.stereo_fusion->bounding_box.first;
180  auto& max_bound = options.stereo_fusion->bounding_box.second;
181  file >> min_bound(0) >> min_bound(1) >> min_bound(2);
182  file >> max_bound(0) >> max_bound(1) >> max_bound(2);
183  } else {
184  std::cout << "WARN: Invalid bounds path: \"" << bbox_path
185  << "\" - continuing without bounds check" << std::endl;
186  }
187  }
188 
189  mvs::StereoFusion fuser(*options.stereo_fusion, workspace_path,
190  workspace_format, pmvs_option_name, input_type);
191 
192  fuser.Start();
193  fuser.Wait();
194 
195  Reconstruction reconstruction;
196 
197  // read data from sparse reconstruction
198  if (workspace_format == "colmap") {
199  reconstruction.Read(JoinPaths(workspace_path, "sparse"));
200  }
201 
202  // overwrite sparse point cloud with dense point cloud from fuser
203  reconstruction.ImportPLY(fuser.GetFusedPoints());
204 
205  std::cout << "Writing output: " << output_path << std::endl;
206 
207  // write output
208  StringToLower(&output_type);
209  if (output_type == "bin") {
210  reconstruction.WriteBinary(output_path);
211  } else if (output_type == "txt") {
212  reconstruction.WriteText(output_path);
213  } else if (output_type == "ply") {
214  WriteBinaryPlyPoints(output_path, fuser.GetFusedPoints());
215  mvs::WritePointsVisibility(output_path + ".vis",
216  fuser.GetFusedPointsVisibility());
217  } else {
218  std::cerr << "ERROR: Invalid `output_type`" << std::endl;
219  return EXIT_FAILURE;
220  }
221 
222  return EXIT_SUCCESS;
223 }
224 
225 } // namespace colmap
void AddRequiredOption(const std::string &name, T *option, const std::string &help_text="")
std::shared_ptr< mvs::PoissonMeshingOptions > poisson_meshing
std::shared_ptr< mvs::DelaunayMeshingOptions > delaunay_meshing
std::shared_ptr< mvs::PatchMatchOptions > patch_match_stereo
void AddDefaultOption(const std::string &name, T *option, const std::string &help_text="")
std::shared_ptr< mvs::StereoFusionOptions > stereo_fusion
void Parse(const int argc, char **argv)
void WriteBinary(const std::string &path) const
void WriteText(const std::string &path) const
void ImportPLY(const std::string &path)
void Read(const std::string &path)
virtual void Start()
Definition: threading.cc:50
virtual void Wait()
Definition: threading.cc:86
const std::vector< std::vector< int > > & GetFusedPointsVisibility() const
Definition: fusion.cc:142
const std::vector< PlyPoint > & GetFusedPoints() const
Definition: fusion.cc:138
QTextStream & endl(QTextStream &stream)
Definition: QtCompat.h:718
void WritePointsVisibility(const std::string &path, const std::vector< std::vector< int >> &points_visibility)
Definition: fusion.cc:635
bool PoissonMeshing(const PoissonMeshingOptions &options, const std::string &input_path, const std::string &output_path)
Definition: meshing.cc:123
int RunPoissonMesher(int argc, char **argv)
Definition: mvs.cc:123
void StringToLower(std::string *str)
Definition: string.cc:193
int RunPatchMatchStereo(int argc, char **argv)
Definition: mvs.cc:81
int RunStereoFuser(int argc, char **argv)
Definition: mvs.cc:138
void WriteBinaryPlyPoints(const std::string &path, const std::vector< PlyPoint > &points, const bool write_normal, const bool write_rgb)
Definition: ply.cc:369
std::string JoinPaths(T const &... paths)
Definition: misc.h:128
int RunDelaunayMesher(int argc, char **argv)
Definition: mvs.cc:43