Commit 7bd6e95f authored by Patrik Huber's avatar Patrik Huber

Added EdgeTopolocy struct and a utils app to create such struct from the Matlab output

parent 348cce7e
......@@ -106,6 +106,7 @@ set(HEADERS
include/eos/morphablemodel/MorphableModel.hpp
include/eos/morphablemodel/Blendshape.hpp
include/eos/morphablemodel/coefficients.hpp
include/eos/morphablemodel/EdgeTopology.hpp
include/eos/morphablemodel/io/cvssp.hpp
include/eos/morphablemodel/io/mat_cerealisation.hpp
include/eos/fitting/affine_camera_estimation.hpp
......
/*
* eos - A 3D Morphable Model fitting library written in modern C++11/14.
*
* File: include/eos/morphablemodel/EdgeTopology.hpp
*
* Copyright 2016 Patrik Huber
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#ifndef EDGETOPOLOGY_HPP_
#define EDGETOPOLOGY_HPP_
#include "cereal/cereal.hpp"
#include "cereal/types/array.hpp"
#include "cereal/types/vector.hpp"
#include "cereal/archives/json.hpp"
#include <array>
#include <vector>
#include <fstream>
namespace eos {
namespace morphablemodel {
/**
* @brief A struct containing a 3D shape model's edge topology.
*
* This struct contains all edges of a 3D mesh, and for each edge, it
* contains the two faces and the two vertices that are adjacent to that
* edge. This is used in the iterated closest edge fitting (ICEF).
*
* Note: The indices are 1-based, so 1 needs to be subtracted before using
* them as mesh indices. An index of 0 as first array element means that
* it's an edge that lies on the mesh boundary, i.e. they are only
* adjacent to one face.
* We should explore a less error-prone way to store this data, but that's
* how it is done in Matlab by the original code.
*
* adjacent_faces.size() is equal to adjacent_vertices.size().
*/
struct EdgeTopology {
std::vector<std::array<int, 2>> adjacent_faces; // num_edges x 2 matrix storing faces adjacent to each edge
std::vector<std::array<int, 2>> adjacent_vertices; // num_edges x 2 matrix storing vertices adjacent to each edge
friend class cereal::access;
/**
* Serialises this class using cereal.
*
* @param[in] ar The archive to serialise to (or to serialise from).
*/
template<class Archive>
void serialize(Archive& archive)
{
archive(CEREAL_NVP(adjacent_faces), CEREAL_NVP(adjacent_vertices));
};
};
/**
* Saves a 3DMM edge topology file to a json file.
*
* @param[in] edge_topology A model's edge topology.
* @param[in] filename The file to write.
* @throws std::runtime_error if unable to open the given file for writing.
*/
void save_edge_topology(EdgeTopology edge_topology, std::string filename)
{
std::ofstream file(filename);
if (file.fail()) {
throw std::runtime_error("Error opening file for writing: " + filename);
}
cereal::JSONOutputArchive output_archive(file);
output_archive(cereal::make_nvp("edge_topology", edge_topology));
};
/**
* Load a 3DMM edge topology file from a json file.
*
* @param[in] filename The file to load the edge topology from.
* @return A struct containing the edge topology.
* @throws std::runtime_error if unable to open the given file for writing.
*/
EdgeTopology load_edge_topology(std::string filename)
{
EdgeTopology edge_topology;
std::ifstream file(filename);
if (file.fail()) {
throw std::runtime_error("Error opening file for reading: " + filename);
}
cereal::JSONInputArchive output_archive(file);
output_archive(cereal::make_nvp("edge_topology", edge_topology));
return edge_topology;
};
} /* namespace morphablemodel */
} /* namespace eos */
#endif /* EDGETOPOLOGY_HPP_ */
......@@ -41,6 +41,10 @@ target_link_libraries(scm-to-cereal ${OpenCV_LIBS} ${Boost_LIBRARIES})
add_executable(bfm-binary-to-cereal bfm-binary-to-cereal.cpp)
target_link_libraries(bfm-binary-to-cereal ${OpenCV_LIBS} ${Boost_LIBRARIES})
# Reads an edgestruct CSV file created from Matlab, and converts it to json:
add_executable(edgestruct-csv-to-json edgestruct-csv-to-json.cpp)
target_link_libraries(edgestruct-csv-to-json ${Boost_LIBRARIES})
# Store a json file as cereal .bin:
add_executable(json-to-cereal-binary json-to-cereal-binary.cpp)
target_link_libraries(json-to-cereal-binary ${OpenCV_LIBS} ${Boost_LIBRARIES})
......@@ -57,3 +61,4 @@ endif()
install(TARGETS scm-to-cereal DESTINATION bin)
install(TARGETS bfm-binary-to-cereal DESTINATION bin)
install(TARGETS json-to-cereal-binary DESTINATION bin)
install(TARGETS edgestruct-csv-to-json DESTINATION bin)
/*
* eos - A 3D Morphable Model fitting library written in modern C++11/14.
*
* File: utils/edgestruct-csv-to-json.cpp
*
* Copyright 2016 Patrik Huber
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "eos/morphablemodel/EdgeTopology.hpp"
#include "boost/program_options.hpp"
#include "boost/filesystem.hpp"
#include "boost/algorithm/string.hpp"
#include <array>
#include <vector>
#include <string>
#include <iostream>
#include <fstream>
using namespace eos;
namespace po = boost::program_options;
namespace fs = boost::filesystem;
using std::cout;
using std::endl;
// Careful, we're loading them from a 1-based indexing file! And store it as 1-based.
// Some values will contain zeros in the first element, which is a special value (= edge at the boundary of the mesh).
std::vector<std::array<int, 2>> read_edgestruct_csv(std::string filename)
{
using std::getline;
using std::string;
std::vector<std::array<int, 2>> vec;
std::ifstream file(filename);
if (!file.is_open()) {
throw std::runtime_error(string("Could not open file: " + filename));
}
string line;
while (getline(file, line))
{
std::vector<string> vals;
boost::split(vals, line, boost::is_any_of(","), boost::token_compress_on);
vec.push_back({ std::stoi(vals[0]), std::stoi(vals[1]) });
}
return vec;
};
/**
* Reads two edgestruct CSV files created from Matlab (one with adjacent faces,
* one with adjacent vertices), converts them to an EdgeTopology struct, and
* stores that as json file.
*/
int main(int argc, char *argv[])
{
fs::path input_adj_faces, input_adj_vertices, outputfile;
try {
po::options_description desc("Allowed options");
desc.add_options()
("help,h",
"display the help message")
("faces,f", po::value<fs::path>(&input_adj_faces)->required(),
"input edgestruct csv file from Matlab with a list of adjacent faces")
("vertices,v", po::value<fs::path>(&input_adj_vertices)->required(),
"input edgestruct csv file from Matlab with a list of adjacent vertices")
("output,o", po::value<fs::path>(&outputfile)->required()->default_value("converted_edge_topology.json"),
"output filename for the converted .json file")
;
po::variables_map vm;
po::store(po::command_line_parser(argc, argv).options(desc).run(), vm);
if (vm.count("help")) {
cout << "Usage: edgestruct-csv-to-json [options]" << endl;
cout << desc;
return EXIT_SUCCESS;
}
po::notify(vm);
}
catch (const po::error& e) {
cout << "Error while parsing command-line arguments: " << e.what() << endl;
cout << "Use --help to display a list of options." << endl;
return EXIT_SUCCESS;
}
morphablemodel::EdgeTopology edge_info;
edge_info.adjacent_faces = read_edgestruct_csv(input_adj_faces.string());
edge_info.adjacent_vertices = read_edgestruct_csv(input_adj_vertices.string());
morphablemodel::save_edge_topology(edge_info, outputfile.string());
cout << "Saved EdgeTopology in json file: " << outputfile.string() << "." << endl;
return EXIT_SUCCESS;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment