Skip to content

Commit

Permalink
[sfm] sfm_data View backward compatibility openMVG#721
Browse files Browse the repository at this point in the history
  • Loading branch information
pmoulon committed Jan 4, 2017
1 parent 51bc2a9 commit f5ecb48
Show file tree
Hide file tree
Showing 4 changed files with 441 additions and 147 deletions.
9 changes: 4 additions & 5 deletions src/openMVG/sfm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,12 @@ set_target_properties(openMVG_sfm PROPERTIES SOVERSION ${OPENMVG_VERSION_MAJOR}
install(TARGETS openMVG_sfm DESTINATION lib EXPORT openMVG-targets)

UNIT_TEST(openMVG sfm_data_io
"openMVG_features;openMVG_sfm;openMVG_system;stlplus")
"openMVG_features;openMVG_sfm")
UNIT_TEST(openMVG sfm_data_BA
"openMVG_multiview_test_data;openMVG_features;openMVG_multiview;openMVG_sfm;openMVG_system;stlplus")
"openMVG_multiview_test_data;openMVG_features;openMVG_sfm")
UNIT_TEST(openMVG sfm_data_utils
"openMVG_features;openMVG_multiview;openMVG_system;openMVG_sfm;stlplus")
"openMVG_features;openMVG_sfm")
UNIT_TEST(openMVG sfm_data_filters
"openMVG_features;openMVG_multiview;openMVG_system;openMVG_sfm;stlplus")
"openMVG_features;openMVG_sfm")

add_subdirectory(pipelines)

350 changes: 350 additions & 0 deletions src/openMVG/sfm/sfm_data_io_cereal.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,350 @@

// Copyright (c) 2016 Pierre MOULON.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.


#include "openMVG/sfm/sfm_data_io_cereal.hpp"

#include "openMVG/sfm/sfm_data.hpp"

#include <cereal/archives/binary.hpp>
#include <cereal/archives/json.hpp>
#include <cereal/archives/portable_binary.hpp>
#include <cereal/archives/xml.hpp>
#include <cereal/types/map.hpp>
#include <cereal/types/string.hpp>
#include <cereal/types/unordered_map.hpp>
#include <cereal/types/vector.hpp>

#include <fstream>
#include <iomanip>
#include <string>

namespace openMVG {
namespace sfm {

/// Here a View description object that was used before OpenMVG v1.1
/// This object is used in order to be able to load old project files.
struct View_version_1
{
std::string s_Img_path; // image path on disk
IndexT id_view; // Id of the view
IndexT id_intrinsic, id_pose; // Index of intrinsics and the pose
IndexT ui_width, ui_height; // image size

// Constructor (use unique index for the view_id)
View_version_1(
const std::string & sImgPath = "",
IndexT view_id = UndefinedIndexT,
IndexT intrinsic_id = UndefinedIndexT,
IndexT pose_id = UndefinedIndexT,
IndexT width = UndefinedIndexT, IndexT height = UndefinedIndexT)
:s_Img_path(sImgPath), id_view(view_id), id_intrinsic(intrinsic_id),
id_pose(pose_id), ui_width(width), ui_height(height)
{}

/**
* @brief Serialization in
* @param ar Archive
*/
template <class Archive>
void load( Archive & ar )
{
//Define a view with two string (base_path & basename)
std::string local_path = s_Img_path;
std::string filename = s_Img_path;

ar(cereal::make_nvp("local_path", local_path),
cereal::make_nvp("filename", filename),
cereal::make_nvp("width", ui_width),
cereal::make_nvp("height", ui_height),
cereal::make_nvp("id_view", id_view),
cereal::make_nvp("id_intrinsic", id_intrinsic),
cereal::make_nvp("id_pose", id_pose));

s_Img_path = stlplus::create_filespec(local_path, filename);
}
};

template <
// JSONInputArchive/ ...
typename archiveType
>
bool Load_Cereal(
SfM_Data & data,
const std::string & filename,
ESfM_Data flags_part)
{
const bool bBinary = stlplus::extension_part(filename) == "bin";

// List which part of the file must be considered
const bool b_views = (flags_part & VIEWS) == VIEWS;
const bool b_intrinsics = (flags_part & INTRINSICS) == INTRINSICS;
const bool b_extrinsics = (flags_part & EXTRINSICS) == EXTRINSICS;
const bool b_structure = (flags_part & STRUCTURE) == STRUCTURE;
const bool b_control_point = (flags_part & CONTROL_POINTS) == CONTROL_POINTS;

//Create the stream and check it is ok
std::ifstream stream(filename.c_str(), std::ios::binary | std::ios::in);
if (!stream.is_open())
return false;

// Data serialization
try
{
archiveType archive(stream);

std::string version;
archive(cereal::make_nvp("sfm_data_version", version));
archive(cereal::make_nvp("root_path", data.s_root_path));

if (b_views)
{
if ( version >= "0.3" )
{
archive(cereal::make_nvp("views", data.views));
}
else // sfm_data version is < to v0.3 => Previous to OpenMVG v1.1
{
// It means that it use the View that does not support inheritance
using Views_v1 = Hash_Map<IndexT, std::shared_ptr<View_version_1>>;
Views_v1 views;
try
{
archive(cereal::make_nvp("views", views));
// Convert views to old to new format
for (const auto v_it : views)
{
data.views[v_it.first] =
std::make_shared<View>(
v_it.second->s_Img_path,
v_it.second->id_view,
v_it.second->id_intrinsic,
v_it.second->id_pose,
v_it.second->ui_width,
v_it.second->ui_height);
}
}
catch (cereal::Exception& e)
{
std::cerr << e.what() << std::endl;
stream.close();
return false;
}
}
}
else
{
if (bBinary)
{
// Binary file requires to read all the member,
// read in a temporary object since the data is not needed.
if ( version >= "0.3" )
{
Views views;
archive(cereal::make_nvp("views", views));
}
else // sfm_data version is < to v0.3 => Previous to OpenMVG v1.1
{
// It means that it use the View that does not support inheritance
using Views_v1 = Hash_Map<IndexT, std::shared_ptr<View_version_1>>;
Views_v1 views;
archive(cereal::make_nvp("views", views));
}
}
}
if (b_intrinsics)
archive(cereal::make_nvp("intrinsics", data.intrinsics));
else
if (bBinary)
{
// Binary file requires to read all the member,
// read in a temporary object since the data is not needed.
Intrinsics intrinsics;
archive(cereal::make_nvp("intrinsics", intrinsics));
}

if (b_extrinsics)
archive(cereal::make_nvp("extrinsics", data.poses));
else
if (bBinary)
{
// Binary file requires to read all the member,
// read in a temporary object since the data is not needed.
Poses poses;
archive(cereal::make_nvp("extrinsics", poses));
}

if (b_structure)
archive(cereal::make_nvp("structure", data.structure));
else
if (bBinary)
{
// Binary file requires to read all the member,
// read in a temporary object since the data is not needed.
Landmarks structure;
archive(cereal::make_nvp("structure", structure));
}

if (version != "0.1") // fast check to assert we are at least using version 0.2
{
if (b_control_point)
archive(cereal::make_nvp("control_points", data.control_points));
else
if (bBinary)
{
// Binary file requires to read all the member,
// read in a temporary object since the data is not needed.
Landmarks control_points;
archive(cereal::make_nvp("control_points", control_points));
}
}
}
catch (const cereal::Exception & e)
{
std::cerr << e.what() << std::endl;
stream.close();
return false;
}
stream.close();
return true;
}

template <
// JSONOutputArchive/ ...
typename archiveType
>
bool Save_Cereal(
const SfM_Data & data,
const std::string & filename,
ESfM_Data flags_part)
{
// List which part of the file must be considered
const bool b_views = (flags_part & VIEWS) == VIEWS;
const bool b_intrinsics = (flags_part & INTRINSICS) == INTRINSICS;
const bool b_extrinsics = (flags_part & EXTRINSICS) == EXTRINSICS;
const bool b_structure = (flags_part & STRUCTURE) == STRUCTURE;
const bool b_control_point = (flags_part & CONTROL_POINTS) == CONTROL_POINTS;

//Create the stream and check it is ok
std::ofstream stream(filename.c_str(), std::ios::binary | std::ios::out);
if (!stream.is_open())
return false;

// Data serialization
{
archiveType archive(stream);
// since OpenMVG 0.9, the sfm_data version 0.2 is introduced
// - it adds control_points storage
// since OpenMVG 1.1, the sfm_data version 0.3 is introduced
// - it introduce polymorphic View data
const std::string version = "0.3";
archive(cereal::make_nvp("sfm_data_version", version));
archive(cereal::make_nvp("root_path", data.s_root_path));

if (b_views)
archive(cereal::make_nvp("views", data.views));
else
archive(cereal::make_nvp("views", Views()));

if (b_intrinsics)
archive(cereal::make_nvp("intrinsics", data.intrinsics));
else
archive(cereal::make_nvp("intrinsics", Intrinsics()));

if (b_extrinsics)
archive(cereal::make_nvp("extrinsics", data.poses));
else
archive(cereal::make_nvp("extrinsics", Poses()));

// Structure -> See for export in another file
if (b_structure)
archive(cereal::make_nvp("structure", data.structure));
else
archive(cereal::make_nvp("structure", Landmarks()));

if (version != "0.1") // fast check to assert we are at least using version 0.2
{
if (b_control_point)
archive(cereal::make_nvp("control_points", data.control_points));
else
archive(cereal::make_nvp("control_points", Landmarks()));
}
}
stream.close();
return true;
}

//
// Explicit template instantiation
//

template bool Load_Cereal
<cereal::BinaryInputArchive>
(
SfM_Data & data,
const std::string & filename,
ESfM_Data flags_part
);

template bool Load_Cereal
<cereal::PortableBinaryInputArchive>
(
SfM_Data & data,
const std::string & filename,
ESfM_Data flags_part
);

template bool Load_Cereal
<cereal::JSONInputArchive>
(
SfM_Data & data,
const std::string & filename,
ESfM_Data flags_part
);

template bool Load_Cereal
<cereal::XMLInputArchive>
(
SfM_Data & data,
const std::string & filename,
ESfM_Data flags_part
);

template bool Save_Cereal
<cereal::BinaryOutputArchive>
(
const SfM_Data & data,
const std::string & filename,
ESfM_Data flags_part
);

template bool Save_Cereal
<cereal::PortableBinaryOutputArchive>
(
const SfM_Data & data,
const std::string & filename,
ESfM_Data flags_part
);

template bool Save_Cereal
<cereal::JSONOutputArchive>
(
const SfM_Data & data,
const std::string & filename,
ESfM_Data flags_part
);

template bool Save_Cereal
<cereal::XMLOutputArchive>
(
const SfM_Data & data,
const std::string & filename,
ESfM_Data flags_part
);

} // namespace sfm
} // namespace openMVG
Loading

0 comments on commit f5ecb48

Please sign in to comment.