I\'m working on a robotics research project where I need to serialize 2D matrices of 3D points: basically each pixel is a 3-vector of floats. These pixels are saved in an Op
You can use msgpack also Create an adaptor https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_adaptor Here is example code. It might be useful:
namespace clmdep_msgpack {
MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) {
namespace adaptor {
//I am sending as bin (int)(int)(int)(char*)
//Mat values: rows,cols,type,data
template<>
struct convert<cv::Mat> {
clmdep_msgpack::object const &operator()(clmdep_msgpack::object const &o, cv::Mat &v) const
{
if(o.type != clmdep_msgpack::type::BIN) throw clmdep_msgpack::type_error();
char *buffer = (char *) o.via.bin.ptr;
int buffer_size = o.via.bin.size;
int rows, cols, type;
rows = *reinterpret_cast<int *>(buffer);
cols = *reinterpret_cast<int *>(buffer + 1 * sizeof(int));
type = *reinterpret_cast<int *>(buffer + 2 * sizeof(int));
cv::Mat(rows, cols, type, (void *) (buffer + 3 * sizeof(int))).copyTo(v);
return o;
}
};
template<>
struct pack<cv::Mat> {
template<typename Stream>
clmdep_msgpack::packer<Stream> &operator()(clmdep_msgpack::packer<Stream> &o, cv::Mat const &v) const
{
// packing member variables as bin.
size_t mat_size;
if(v.isContinuous()) {
mat_size = v.total() * v.elemSize();
} else {
mat_size = v.step[v.dims - 1];
for(int t = 0; t < v.dims; t++) {
// calculate total size of multi dimensional matrix by multiplying dimensions
mat_size *= v.size[t];
}
}
int extra_ints = 3;
int buffer_size = extra_ints * sizeof(int) + mat_size;
// Allocate destination image buffer
char *imagebuffer = new char[buffer_size];
int type = v.type();
std::memcpy(imagebuffer, &(v.rows), sizeof(int));
std::memcpy(imagebuffer + 1 * sizeof(int), &(v.cols), sizeof(int));
std::memcpy(imagebuffer + 2 * sizeof(int), &type, sizeof(int));
if(v.isContinuous()) {
std::memcpy((imagebuffer + 3 * sizeof(int)), (char *) v.data, mat_size);
} else {
const size_t rowsize = v.step[v.dims - 1] * v.size[v.dims - 1];
size_t coordinates[v.dims - 1] = {0};
size_t srcptr = 0, dptr = extra_ints * sizeof(int);
while(dptr < buffer_size) {
// we copy entire rows at once, so lowest iterator is always [dims-2]
// this is legal since OpenCV does not use 1 dimensional matrices internally (a 1D matrix is a 2d matrix with only 1 row)
std::memcpy(&imagebuffer[dptr], &(((char *) v.data)[srcptr]), rowsize);
// destination matrix has no gaps so rows follow each other directly
dptr += rowsize;
// src matrix can have gaps so we need to calculate the address of the start of the next row the hard way
// see *brief* text in opencv2/core/mat.hpp for address calculation
coordinates[v.dims - 2]++;
srcptr = 0;
for(int t = v.dims - 2; t >= 0; t--) {
if(coordinates[t] >= v.size[t]) {
if(t == 0) break;
coordinates[t] = 0;
coordinates[t - 1]++;
}
srcptr += v.step[t] * coordinates[t];
}
}
}
o.pack_bin(buffer_size);
o.pack_bin_body(imagebuffer, buffer_size);
return o;
}
};
template<>
struct object_with_zone<cv::Mat> {
void operator()(clmdep_msgpack::object::with_zone &o, cv::Mat const &v) const
{
size_t mat_size;
if(v.isContinuous()) {
mat_size = v.total() * v.elemSize();
} else {
mat_size = v.step[v.dims - 1];
for(int t = 0; t < v.dims; t++) {
// calculate total size of multi dimensional matrix by multiplying dimensions
mat_size *= v.size[t];
}
}
int extra_ints = 3;
int buffer_size = extra_ints * sizeof(int) + mat_size;
// Allocate destination image buffer
char *imagebuffer = new char[buffer_size];
int type = v.type();
std::memcpy(imagebuffer, &(v.rows), sizeof(int));
std::memcpy(imagebuffer + 1 * sizeof(int), &(v.cols), sizeof(int));
std::memcpy(imagebuffer + 2 * sizeof(int), &type, sizeof(int));
if(v.isContinuous()) {
std::memcpy((imagebuffer + 3 * sizeof(int)), (char *) v.data, mat_size);
} else {
const size_t rowsize = v.step[v.dims - 1] * v.size[v.dims - 1];
size_t coordinates[v.dims - 1] = {0};
size_t srcptr = 0, dptr = extra_ints * sizeof(int);
while(dptr < buffer_size) {
// we copy entire rows at once, so lowest iterator is always [dims-2]
// this is legal since OpenCV does not use 1 dimensional matrices internally (a 1D matrix is a 2d matrix with only 1 row)
std::memcpy(&imagebuffer[dptr], &(((char *) v.data)[srcptr]), rowsize);
// destination matrix has no gaps so rows follow each other directly
dptr += rowsize;
// src matrix can have gaps so we need to calculate the address of the start of the next row the hard way
// see *brief* text in opencv2/core/mat.hpp for address calculation
coordinates[v.dims - 2]++;
srcptr = 0;
for(int t = v.dims - 2; t >= 0; t--) {
if(coordinates[t] >= v.size[t]) {
if(t == 0) break;
coordinates[t] = 0;
coordinates[t - 1]++;
}
srcptr += v.step[t] * coordinates[t];
}
}
}
o.type = type::BIN;
o.via.bin.size = buffer_size;
o.via.bin.ptr = imagebuffer;
}
};
} // namespace adaptor
} // MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS)
} // names