eos  0.7.1
mat_cerealisation.hpp
1 /*
2 * Eos - A 3D Morphable Model fitting library written in modern C++11/14.
3 *
4 * File: include/eos/morphablemodel/io/mat_cerealisation.hpp
5  *
6  * Copyright 2015, 2016 Patrik Huber
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 #pragma once
21 
22 #ifndef MATCEREALISATION_HPP_
23 #define MATCEREALISATION_HPP_
24 
25 #include "cereal/cereal.hpp"
26 
27 #include "opencv2/core/core.hpp"
28 
38 namespace cv {
39 
48 template<class Archive, cereal::traits::DisableIf<cereal::traits::is_text_archive<Archive>::value>
49  = cereal::traits::sfinae>
50 void save(Archive& ar, const cv::Mat& mat)
51 {
52  int rows, cols, type;
53  bool continuous;
54 
55  rows = mat.rows;
56  cols = mat.cols;
57  type = mat.type();
58  continuous = mat.isContinuous();
59 
60  ar & rows & cols & type & continuous;
61 
62  if (continuous) {
63  const int data_size = rows * cols * static_cast<int>(mat.elemSize());
64  auto mat_data = cereal::binary_data(mat.ptr(), data_size);
65  ar & mat_data;
66  }
67  else {
68  const int row_size = cols * static_cast<int>(mat.elemSize());
69  for (int i = 0; i < rows; i++) {
70  auto row_data = cereal::binary_data(mat.ptr(i), row_size);
71  ar & row_data;
72  }
73  }
74 };
75 
84 template<class Archive, cereal::traits::DisableIf<cereal::traits::is_text_archive<Archive>::value>
85  = cereal::traits::sfinae>
86 void load(Archive& ar, cv::Mat& mat)
87 {
88  int rows, cols, type;
89  bool continuous;
90 
91  ar & rows & cols & type & continuous;
92 
93  if (continuous) {
94  mat.create(rows, cols, type);
95  const int data_size = rows * cols * static_cast<int>(mat.elemSize());
96  auto mat_data = cereal::binary_data(mat.ptr(), data_size);
97  ar & mat_data;
98  }
99  else {
100  mat.create(rows, cols, type);
101  const int row_size = cols * static_cast<int>(mat.elemSize());
102  for (int i = 0; i < rows; i++) {
103  auto row_data = cereal::binary_data(mat.ptr(i), row_size);
104  ar & row_data;
105  }
106  }
107 };
108 
109 
126 template <class Archive,
127  cereal::traits::EnableIf<cereal::traits::is_text_archive<Archive>::value>
128  = cereal::traits::sfinae>
129  void save(Archive& ar, const cv::Mat& mat)
130 {
131  int rows, cols, type;
132  bool continuous;
133 
134  rows = mat.rows;
135  cols = mat.cols;
136  type = mat.type();
137  continuous = mat.isContinuous();
138 
139  //ar & rows & cols & type & continuous;
140  assert(mat.dims == 2); // correct?
141 
142  if (continuous) { // We go row by row anyway so no need for this distinction?
143  //const int data_size = rows * cols * static_cast<int>(mat.elemSize());
144  //std::vector<float> test(mat.begin<float>(), mat.end<float>());
145  //ar & test;
146 
147  std::vector<std::vector<float>> mat_data;
148  for (int i = 0; i < rows; i++) {
149  Mat this_row = mat.row(i); // need a temporary, otherwise goes up to 8GB RAM usage
150  mat_data.push_back(std::vector<float>(this_row.begin<float>(), this_row.end<float>()));
151  }
152  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?
153  }
154  else {
155  const int row_size = cols * static_cast<int>(mat.elemSize());
156  for (int i = 0; i < rows; i++) {
157  //auto row_data = cereal::binary_data(mat.ptr(i), row_size);
158  //ar & row_data;
159  }
160  }
161 };
162 
163 
175 template <class Archive,
176  cereal::traits::EnableIf<cereal::traits::is_text_archive<Archive>::value>
177  = cereal::traits::sfinae>
178  void load(Archive& ar, cv::Mat& mat)
179 {
180  //int rows, cols, type;
181  //bool continuous;
182 
183  //ar & rows & cols & type & continuous;
184 
185  std::vector<std::vector<float>> mat_data;
186  ar & mat_data;
187  assert(mat_data.size() > 0); // hmm can't store empty cv::Mat's... not so nice. Will create problems with SFM shape-only models?
188  int rows = static_cast<int>(mat_data.size());
189  int cols = static_cast<int>(mat_data[0].size());
190  mat.create(rows, cols, CV_32FC1);
191  for (int r = 0; r < rows; ++r) {
192  for (int c = 0; c < cols; ++c) {
193  mat.at<float>(r, c) = mat_data[r][c];
194  }
195  }
196 
197 /* mat.create(rows, cols, type);
198  const int data_size = rows * cols * static_cast<int>(mat.elemSize());
199  auto mat_data = cereal::binary_data(mat.ptr(), data_size);
200  ar & mat_data;
201 
202  mat.create(rows, cols, type);
203  const int row_size = cols * static_cast<int>(mat.elemSize());
204  for (int i = 0; i < rows; i++) {
205  auto row_data = cereal::binary_data(mat.ptr(i), row_size);
206  ar & row_data;
207  }*/
208 };
209 
210 
217 template <class Archive>
218 void serialize(Archive& ar, cv::Vec2f& vec)
219 {
220  ar(vec[0], vec[1]);
221 };
222 
223 } /* namespace cv */
224 
225 #endif /* MATCEREALISATION_HPP_ */
void load(Archive &ar, cv::Mat &mat)
De-serialise a cv::Mat using cereal.
Definition: mat_cerealisation.hpp:86
Serialisation of OpenCV cv::Mat matrices for the serialisation library cereal (http://uscilab.github.io/cereal/index.html).
Definition: mat_cerealisation.hpp:38
void save(Archive &ar, const cv::Mat &mat)
Serialise a cv::Mat using cereal.
Definition: mat_cerealisation.hpp:50
void serialize(Archive &ar, cv::Vec2f &vec)
Serialisation of a cv::Vec2f using cereal.
Definition: mat_cerealisation.hpp:218