1 // This file is part of OpenMVG, an Open Multiple View Geometry C++ library.
2 
3 // Copyright (c) 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 #ifndef OPENMVG_SFM_SFM_DATA_IO_BAF_HPP
10 #define OPENMVG_SFM_SFM_DATA_IO_BAF_HPP
11 
12 #include <algorithm>
13 #include <fstream>
14 #include <string>
15 #include <vector>
16 
17 #include "openMVG/sfm/sfm_data_io.hpp"
18 #include "third_party/stlplus3/filesystemSimplified/file_system.hpp"
19 
20 namespace openMVG {
21 namespace sfm {
22 
23 /// Save SfM_Data in an ASCII BAF (Bundle Adjustment File).
24 // --Header
25 // #Intrinsics
26 // #Poses
27 // #Landmarks
28 // --Data
29 // Intrinsic parameters [foc ppx ppy, ...]
30 // Poses [angle axis, camera center]
31 // Landmarks [X Y Z #observations id_intrinsic id_pose x y ...]
32 //--
33 //- Export also a _imgList.txt file with View filename and id_intrinsic & id_pose.
34 // filename id_intrinsic id_pose
35 // The ids allow to establish a link between 3D point observations & the corresponding views
36 //--
37 // Export missing poses as Identity pose to keep tracking of the original id_pose indexes
Save_BAF(const SfM_Data & sfm_data,const std::string & filename,ESfM_Data flags_part)38 inline bool Save_BAF(
39   const SfM_Data & sfm_data,
40   const std::string & filename,
41   ESfM_Data flags_part)
42 {
43   std::ofstream stream(filename);
44   if (!stream)
45     return false;
46 
47   bool bOk = false;
48   {
49     stream
50       << sfm_data.GetIntrinsics().size() << '\n'
51       << sfm_data.GetViews().size() << '\n'
52       << sfm_data.GetLandmarks().size() << '\n';
53 
54     const Intrinsics & intrinsics = sfm_data.GetIntrinsics();
55     for (const auto & iterIntrinsic : intrinsics )
56     {
57       //get params
58       const std::vector<double> intrinsicsParams = iterIntrinsic.second->getParams();
59       std::copy(intrinsicsParams.begin(), intrinsicsParams.end(),
60         std::ostream_iterator<double>(stream, " "));
61       stream << '\n';
62     }
63 
64     const Poses & poses = sfm_data.GetPoses();
65     for ( const auto & iterV : sfm_data.GetViews() )
66     {
67       const View * view = iterV.second.get();
68       if (!sfm_data.IsPoseAndIntrinsicDefined(view))
69       {
70         const Mat3 R = Mat3::Identity();
71         const double * rotation = R.data();
72         std::copy(rotation, rotation+9, std::ostream_iterator<double>(stream, " "));
73         const Vec3 C = Vec3::Zero();
74         const double * center = C.data();
75         std::copy(center, center+3, std::ostream_iterator<double>(stream, " "));
76         stream << '\n';
77       }
78       else
79       {
80         // [Rotation col major 3x3; camera center 3x1]
81         const double * rotation = poses.at(view->id_pose).rotation().data();
82         std::copy(rotation, rotation+9, std::ostream_iterator<double>(stream, " "));
83         const double * center = poses.at(view->id_pose).center().data();
84         std::copy(center, center+3, std::ostream_iterator<double>(stream, " "));
85         stream << '\n';
86       }
87     }
88 
89     const Landmarks & landmarks = sfm_data.GetLandmarks();
90     for (const auto & iterLandmarks : landmarks )
91     {
92       // Export visibility information
93       // X Y Z #observations id_cam id_pose x y ...
94       const double * X = iterLandmarks.second.X.data();
95       std::copy(X, X+3, std::ostream_iterator<double>(stream, " "));
96       const Observations & obs = iterLandmarks.second.obs;
97       stream << obs.size() << " ";
98       for ( const auto & iterOb : obs )
99       {
100         const IndexT id_view = iterOb.first;
101         const View * v = sfm_data.GetViews().at(id_view).get();
102         stream
103           << v->id_intrinsic << ' '
104           << v->id_pose << ' '
105           << iterOb.second.x(0) << ' ' << iterOb.second.x(1) << ' ';
106       }
107       stream << '\n';
108     }
109 
110     stream.flush();
111     bOk = stream.good();
112     stream.close();
113   }
114 
115   // Export View filenames & ids as an imgList.txt file
116   {
117     const std::string sFile = stlplus::create_filespec(
118       stlplus::folder_part(filename), stlplus::basename_part(filename) + std::string("_imgList"), "txt");
119 
120     stream.open(sFile);
121     if (!stream)
122       return false;
123     for ( const auto & iterV : sfm_data.GetViews() )
124     {
125       const std::string sView_filename = stlplus::create_filespec(sfm_data.s_root_path,
126         iterV.second->s_Img_path);
127       stream
128         << sView_filename
129         << ' ' << iterV.second->id_intrinsic
130         << ' ' << iterV.second->id_pose << "\n";
131     }
132     stream.flush();
133     bOk = stream.good();
134     stream.close();
135   }
136   return bOk;
137 }
138 
139 } // namespace sfm
140 } // namespace openMVG
141 
142 #endif // OPENMVG_SFM_SFM_DATA_IO_BAF_HPP
143