1 // This file is part of OpenMVG, an Open Multiple View Geometry C++ library.
2
3 // Copyright (c) 2012, 2013, 2015 Pierre MOULON.
4
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
9 #include "openMVG/cameras/Camera_Pinhole.hpp"
10 #include "openMVG/image/image_io.hpp"
11 #include "openMVG/sfm/sfm_data.hpp"
12 #include "openMVG/sfm/sfm_data_io.hpp"
13 #include "openMVG/system/logger.hpp"
14
15 using namespace openMVG;
16 using namespace openMVG::cameras;
17 using namespace openMVG::geometry;
18 using namespace openMVG::sfm;
19
20 #include "third_party/cmdLine/cmdLine.h"
21 #include "third_party/stlplus3/filesystemSimplified/file_system.hpp"
22
23 #include <fstream>
24
main(int argc,char ** argv)25 int main(int argc, char **argv)
26 {
27 CmdLine cmd;
28
29 std::string sSfM_Data_Filename;
30 std::string sOutDir = "";
31
32 cmd.add( make_option('i', sSfM_Data_Filename, "sfmdata") );
33 cmd.add( make_option('o', sOutDir, "outdir") );
34
35 try {
36 if (argc == 1) throw std::string("Invalid command line parameter.");
37 cmd.process(argc, argv);
38 } catch (const std::string& s) {
39 OPENMVG_LOG_INFO << "Usage: " << argv[0] << '\n'
40 << "[-i|--sfmdata] filename, the SfM_Data file to convert\n"
41 << "[-o|--outdir] path.";
42
43 OPENMVG_LOG_ERROR << s;
44 return EXIT_FAILURE;
45 }
46
47 OPENMVG_LOG_INFO << " You called : " << argv[0]
48 << "\n--sfmdata " << sSfM_Data_Filename
49 << "\n--outdir " << sOutDir;
50
51 bool bOneHaveDisto = false;
52
53 // Create output dir
54 if (!stlplus::folder_exists(sOutDir))
55 stlplus::folder_create( sOutDir );
56
57 // Read the SfM scene
58 SfM_Data sfm_data;
59 if (!Load(sfm_data, sSfM_Data_Filename, ESfM_Data(VIEWS|INTRINSICS|EXTRINSICS))) {
60 OPENMVG_LOG_ERROR << "The input SfM_Data file \""<< sSfM_Data_Filename << "\" cannot be read.";
61 return EXIT_FAILURE;
62 }
63
64 for (Views::const_iterator iter = sfm_data.GetViews().begin();
65 iter != sfm_data.GetViews().end(); ++iter)
66 {
67 const View * view = iter->second.get();
68 if (!sfm_data.IsPoseAndIntrinsicDefined(view))
69 continue;
70
71 // Valid view, we can ask a pose & intrinsic data
72 const Pose3 pose = sfm_data.GetPoseOrDie(view);
73 Intrinsics::const_iterator iterIntrinsic = sfm_data.GetIntrinsics().find(view->id_intrinsic);
74 const IntrinsicBase * cam = iterIntrinsic->second.get();
75
76 if (!cameras::isPinhole(cam->getType()))
77 continue;
78 const Pinhole_Intrinsic * pinhole_cam = static_cast<const Pinhole_Intrinsic *>(cam);
79
80 // Extrinsic
81 const Vec3 t = pose.translation();
82 const Mat3 R = pose.rotation();
83 // Intrinsic
84 const double f = pinhole_cam->focal();
85 const Vec2 pp = pinhole_cam->principal_point();
86
87 // Image size in px
88 const int w = pinhole_cam->w();
89 const int h = pinhole_cam->h();
90
91 // We can now create the .cam file for the View in the output dir
92 std::ofstream outfile( stlplus::create_filespec(
93 sOutDir, stlplus::basename_part(view->s_Img_path), "cam" ).c_str() );
94 // See https://github.com/nmoehrle/mvs-texturing/blob/master/apps/texrecon/arguments.cpp
95 // for full specs
96 const int largerDim = w > h ? w : h;
97 outfile << t(0) << " " << t(1) << " " << t(2) << " "
98 << R(0,0) << " " << R(0,1) << " " << R(0,2) << " "
99 << R(1,0) << " " << R(1,1) << " " << R(1,2) << " "
100 << R(2,0) << " " << R(2,1) << " " << R(2,2) << "\n"
101 << f / largerDim << " 0 0 1 " << pp(0) / w << " " << pp(1) / h;
102 outfile.close();
103
104 if (cam->have_disto())
105 bOneHaveDisto = true;
106 }
107
108 const std::string sUndistMsg = bOneHaveDisto ? "undistorded" : "";
109 const std::string sQuitMsg = std::string("Your SfM_Data file was succesfully converted!\n") +
110 "Now you can copy your " + sUndistMsg + " images in the \"" + sOutDir + "\" directory and run MVS Texturing";
111 OPENMVG_LOG_INFO << sQuitMsg;
112 return EXIT_SUCCESS;
113 }
114