Serializing Opencv Mat_<Vec3F>

Serializing OpenCV Mat_Vec3f

Edit: Christoph Heindl has commented on this post with a link to his blog where he has improved on this serialisation code. Highly recommended!

http://cheind.wordpress.com/2011/12/06/serialization-of-cvmat-objects-using-boost/

--

For whoever it may benefit: Some code to serialize Mat& with boost::serialization

I haven't tested with multi-channel data, but everything should work fine.

#include <iostream>
#include <fstream>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/split_free.hpp>
#include <boost/serialization/vector.hpp>

BOOST_SERIALIZATION_SPLIT_FREE(Mat)
namespace boost {
namespace serialization {

/*** Mat ***/
template<class Archive>
void save(Archive & ar, const Mat& m, const unsigned int version)
{
size_t elemSize = m.elemSize(), elemType = m.type();

ar & m.cols;
ar & m.rows;
ar & elemSize;
ar & elemType; // element type.
size_t dataSize = m.cols * m.rows * m.elemSize();

//cout << "Writing matrix data rows, cols, elemSize, type, datasize: (" << m.rows << "," << m.cols << "," << m.elemSize() << "," << m.type() << "," << dataSize << ")" << endl;

for (size_t dc = 0; dc < dataSize; ++dc) {
ar & m.data[dc];
}
}

template<class Archive>
void load(Archive & ar, Mat& m, const unsigned int version)
{
int cols, rows;
size_t elemSize, elemType;

ar & cols;
ar & rows;
ar & elemSize;
ar & elemType;

m.create(rows, cols, elemType);
size_t dataSize = m.cols * m.rows * elemSize;

//cout << "reading matrix data rows, cols, elemSize, type, datasize: (" << m.rows << "," << m.cols << "," << m.elemSize() << "," << m.type() << "," << dataSize << ")" << endl;

for (size_t dc = 0; dc < dataSize; ++dc) {
ar & m.data[dc];
}
}

}
}

Now, mat can be serialized and deserialized as following:

    void saveMat(Mat& m, string filename) {
ofstream ofs(filename.c_str());
boost::archive::binary_oarchive oa(ofs);
//boost::archive::text_oarchive oa(ofs);
oa << m;
}

void loadMat(Mat& m, string filename) {
std::ifstream ifs(filename.c_str());
boost::archive::binary_iarchive ia(ifs);
//boost::archive::text_iarchive ia(ifs);
ia >> m;
}

I've used the binary_oarchive and binary_iarchive here to keep the memory usage down. The binary format doesn't provide portability between platforms, but if desired the text_oarchive/iarchive can be used.

How to serialize OpenCV Mat with boost XML archive

Need to add this somewhere in a included header:

namespace boost {
namespace serialization {

template<class Archive>
inline void serialize(Archive & ar, cv::Mat& m, const unsigned int version) {
int cols = m.cols;
int rows = m.rows;
size_t elemSize = m.elemSize();
size_t elemType = m.type();

ar & BOOST_SERIALIZATION_NVP(cols);
ar & BOOST_SERIALIZATION_NVP(rows);
ar & BOOST_SERIALIZATION_NVP(elemSize);
ar & BOOST_SERIALIZATION_NVP(elemType); // element type.

if(m.type() != elemType || m.rows != rows || m.cols != cols) {
m = cv::Mat(rows, cols, elemType, cv::Scalar(0));
}

size_t dataSize = cols * rows * elemSize;
cout << " datasize is " << dataSize;

for (size_t dc = 0; dc < dataSize; dc++) {
std::stringstream ss;
ss << "elem_"<<dc;
ar & boost::serialization::make_nvp(ss.str().c_str(), m.data[dc]);
}

}
}
}

How to write a Float Mat to a file in OpenCV

Using pure OpenCV API calls:

// Declare what you need
cv::FileStorage file("some_name.ext", cv::FileStorage::WRITE);
cv::Mat someMatrixOfAnyType;

// Write to file!
file << "matName" << someMatrixOfAnyType;

The file extension can be xml or yml.
In both cases you get a small header that you can easily remove/parse, then you have access to the data in a floating point format.
I used this approach successfully (with yml files) to get data into Matlab and Matplotlib

To get the data:

  1. open the file with any editor
  2. then suppress all the text and numbers except the content of the data tag (i.e., the pixel values).
  3. When done, save your file with a txt or csv extension and open it with matlab (drag-and-drop works).

Voilà. You may have to reshape the resulting matrix in matlab command line if it didn't guess correctly the image size.

Opencv:: Convert Mat_ Vec3f to normal 8 bit color image

Check this code snippet,

Mat_<Vec3f> blend;//fill it 
Mat dst = Mat(blend);

Fore more info read here

OpenCV scalar used with template programming causes compilation error

You can't do it this way since Scalar has different number of dimensions than your mat and the operator = is not resolved in such the case. It's best explained by this inheritance diagram from OpenCV documentation:

Sample Image

As you can see, scalar is a 4 dimensional vector with template type, while each element in your mat is always 1 dimension, but different number of channels denoted as cn. You need to assign the value to each Mat element explicitly using cv::Scalar::operator[] to access each channel separately.

C++ Opencv: Try to print Mat value, but get empty prints

Miki's comment is correct but here is an explanation why the mentioned error occurred:

While initializing Mat M by:

Mat M(Size(100, 200), CV_32FC(n_Channel));

The Matrix type of M is set to 32 bit and each pixel in the 3 channelled Mat M holds float value ranging from 0 to 1.0. Now to print the values of the pixels in Mat M it is necessary to use correct specifier, in case of Mat M , it should be Vec3f, that is Vector with 3 float entries instead of Vec3b, that is Vector with 3 byte entries(would have been suitable for CV_8UC3).



Related Topics



Leave a reply



Submit