Commit cc664c78 authored by Patrik Huber's avatar Patrik Huber

Added experimental serialisation to JSON for cv::Mat's

This is needed by the json-to-cereal-binary app to read the JSON generated from the Matlab BFM converter script.
parent 12db2af2
/* /*
* superviseddescent: A C++11 implementation of the supervised descent * Eos - A 3D Morphable Model fitting library written in modern C++11/14.
* optimisation method *
* File: superviseddescent/matcerealisation.hpp * File: include/eos/morphablemodel/io/mat_cerealisation.hpp
* *
* Copyright 2015 Patrik Huber * Copyright 2015, 2016 Patrik Huber
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -29,6 +29,11 @@ ...@@ -29,6 +29,11 @@
/** /**
* @brief Serialisation of OpenCV \c cv::Mat matrices for the serialisation * @brief Serialisation of OpenCV \c cv::Mat matrices for the serialisation
* library cereal (http://uscilab.github.io/cereal/index.html). * library cereal (http://uscilab.github.io/cereal/index.html).
*
* Contains serialisation for \c cv::Mat matrices to binary archives, and
* serialisation of cv::Vec2f.
*
* Contains also an experimental serialisation to save/load cv::Mat's from JSON.
*/ */
namespace cv { namespace cv {
...@@ -40,7 +45,8 @@ namespace cv { ...@@ -40,7 +45,8 @@ namespace cv {
* @param[in] ar The archive to serialise to. * @param[in] ar The archive to serialise to.
* @param[in] mat The matrix to serialise. * @param[in] mat The matrix to serialise.
*/ */
template<class Archive> template<class Archive, cereal::traits::DisableIf<cereal::traits::is_text_archive<Archive>::value>
= cereal::traits::sfinae>
void save(Archive& ar, const cv::Mat& mat) void save(Archive& ar, const cv::Mat& mat)
{ {
int rows, cols, type; int rows, cols, type;
...@@ -75,7 +81,8 @@ void save(Archive& ar, const cv::Mat& mat) ...@@ -75,7 +81,8 @@ void save(Archive& ar, const cv::Mat& mat)
* @param[in] ar The archive to deserialise from. * @param[in] ar The archive to deserialise from.
* @param[in] mat The matrix to deserialise into. * @param[in] mat The matrix to deserialise into.
*/ */
template<class Archive> template<class Archive, cereal::traits::DisableIf<cereal::traits::is_text_archive<Archive>::value>
= cereal::traits::sfinae>
void load(Archive& ar, cv::Mat& mat) void load(Archive& ar, cv::Mat& mat)
{ {
int rows, cols, type; int rows, cols, type;
...@@ -99,6 +106,108 @@ void load(Archive& ar, cv::Mat& mat) ...@@ -99,6 +106,108 @@ void load(Archive& ar, cv::Mat& mat)
} }
}; };
/**
* @brief Serialise a cv::Mat using cereal, for text archives (JSON specifically).
*
* Experimental: This specialisation is enabled for text archives (e.g. XML, JSON),
* and was created to convert the JSON output from the BFM Matlab converter script
* to a cereal binary model.
*
* Notes:
* - Only for 2-dim matrices, and float values, i.e. CV_32FC1 cv::Mat's.
* Actually, _only_ 32FC1, because of the load() method. In fact, maybe we should
* store the type, since we're storing cv::Mat's.
* - Writes the data row-wise to a json array? or a json object?
*
* @param[in] ar The archive to serialise to.
* @param[in] mat The matrix to serialise.
*/
template <class Archive,
cereal::traits::EnableIf<cereal::traits::is_text_archive<Archive>::value>
= cereal::traits::sfinae>
void save(Archive& ar, const cv::Mat& mat)
{
int rows, cols, type;
bool continuous;
rows = mat.rows;
cols = mat.cols;
type = mat.type();
continuous = mat.isContinuous();
//ar & rows & cols & type & continuous;
assert(mat.dims == 2); // correct?
if (continuous) { // We go row by row anyway so no need for this distinction?
//const int data_size = rows * cols * static_cast<int>(mat.elemSize());
//std::vector<float> test(mat.begin<float>(), mat.end<float>());
//ar & test;
std::vector<std::vector<float>> mat_data;
for (int i = 0; i < rows; i++) {
Mat this_row = mat.row(i); // need a temporary, otherwise goes up to 8GB RAM usage
mat_data.push_back(std::vector<float>(this_row.begin<float>(), this_row.end<float>()));
}
ar & cereal::make_nvp("data", mat_data); // Can we somehow not give this a name and make it like the "root" node, part of the parent object? Maybe look at the std::string serialisation?
}
else {
const int row_size = cols * static_cast<int>(mat.elemSize());
for (int i = 0; i < rows; i++) {
//auto row_data = cereal::binary_data(mat.ptr(i), row_size);
//ar & row_data;
}
}
};
/**
* @brief De-serialise a cv::Mat using cereal, for text archives (JSON specifically).
*
* Experimental: This specialisation is enabled for text archives (e.g. XML, JSON),
* and was created to convert the JSON output from the BFM Matlab converter script
* to a cereal binary model.
* See the notes of the save() method!
*
* @param[in] ar The archive to deserialise from.
* @param[in] mat The matrix to deserialise into.
*/
template <class Archive,
cereal::traits::EnableIf<cereal::traits::is_text_archive<Archive>::value>
= cereal::traits::sfinae>
void load(Archive& ar, cv::Mat& mat)
{
//int rows, cols, type;
//bool continuous;
//ar & rows & cols & type & continuous;
std::vector<std::vector<float>> mat_data;
ar & mat_data;
assert(mat_data.size() > 0); // hmm can't store empty cv::Mat's... not so nice. Will create problems with SFM shape-only models?
int rows = static_cast<int>(mat_data.size());
int cols = static_cast<int>(mat_data[0].size());
mat.create(rows, cols, CV_32FC1);
for (int r = 0; r < rows; ++r) {
for (int c = 0; c < cols; ++c) {
mat.at<float>(r, c) = mat_data[r][c];
}
}
/* mat.create(rows, cols, type);
const int data_size = rows * cols * static_cast<int>(mat.elemSize());
auto mat_data = cereal::binary_data(mat.ptr(), data_size);
ar & mat_data;
mat.create(rows, cols, type);
const int row_size = cols * static_cast<int>(mat.elemSize());
for (int i = 0; i < rows; i++) {
auto row_data = cereal::binary_data(mat.ptr(i), row_size);
ar & row_data;
}*/
};
/** /**
* @brief Serialisation of a cv::Vec2f using cereal. * @brief Serialisation of a cv::Vec2f using cereal.
* *
...@@ -111,6 +220,6 @@ void serialize(Archive& ar, cv::Vec2f& vec) ...@@ -111,6 +220,6 @@ void serialize(Archive& ar, cv::Vec2f& vec)
ar(vec[0], vec[1]); ar(vec[0], vec[1]);
}; };
} } /* namespace cv */
#endif /* MATCEREALISATION_HPP_ */ #endif /* MATCEREALISATION_HPP_ */
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