序列化OpenCV Mat_ <Vec3f>

bto*_*own 16 c++ serialization opencv

我正在进行机器人研究项目,我需要序列化3D点的2D矩阵:基本上每个像素都是3个浮点数矢量.这些像素保存在OpenCV矩阵中,它们需要通过进程间通信发送并保存到文件中以便在多台计算机上进行处理.我想尽快以端点/体系结构独立,节省空间的方式对它们进行序列化.cv::imencode 这里是完美的,除了它只适用于8位和16位元素,我们不想失去任何精度.这些文件不需要是人类可读的(尽管我们现在这样做是为了确保数据的可移植性,而且速度非常慢).是否有最佳实践或优雅的方法?

谢谢!

use*_*427 17

较早的答案是好的,但是当你想要序列化感兴趣的区域(以及其他东西)时,它们不适用于非连续矩阵.此外,没有必要序列化,elemSize()因为这是从type值派生的.

这里有一些代码可以工作而不管连续性(包含/名称空间)

#pragma once

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/utility.hpp>
#include <opencv2/opencv.hpp>

namespace boost {
namespace serialization {

template<class Archive>
void serialize(Archive &ar, cv::Mat& mat, const unsigned int)
{
    int cols, rows, type;
    bool continuous;

    if (Archive::is_saving::value) {
        cols = mat.cols; rows = mat.rows; type = mat.type();
        continuous = mat.isContinuous();
    }

    ar & cols & rows & type & continuous;

    if (Archive::is_loading::value)
        mat.create(rows, cols, type);

    if (continuous) {
        const unsigned int data_size = rows * cols * mat.elemSize();
        ar & boost::serialization::make_array(mat.ptr(), data_size);
    } else {
        const unsigned int row_size = cols*mat.elemSize();
        for (int i = 0; i < rows; i++) {
            ar & boost::serialization::make_array(mat.ptr(i), row_size);
        }
    }

}

} // namespace serialization
} // namespace boost
Run Code Online (Sandbox Code Playgroud)

  • 这是序列化cv :: Mat的最好,最简单和最完整的答案。它比@TumbleCow和Christoph Heindl的博客提供的解决方案更加完整。感谢您的分享! (2认同)

Tin*_*ank 16

编辑:Christoph Heindl对这篇文章发表了评论,并附有他的博客链接,他对此序列化代码进行了改进.强烈推荐!

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

-

对于任何可能受益的人:一些用于序列化Mat和使用boost :: serialization的代码
我没有使用多通道数据进行测试,但一切都应该可以正常工作.

#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];
        }
    }

}
}
Run Code Online (Sandbox Code Playgroud)

现在,mat可以序列化和反序列化如下:

    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;
    }
Run Code Online (Sandbox Code Playgroud)

我在这里使用了binary_oarchive和binary_iarchive来降低内存使用率.二进制格式不提供平台之间的可移植性,但如果需要,可以使用text_oarchive/iarchive.

  • 两个改进:您可以使用`boost :: serialization :: make_array`而不是自定义for循环来保存单个矩阵元素,并且可以使用boost.iostreams轻松添加无损zlib压缩.我编写了一个[post](http://cheind.wordpress.com/2011/12/06/serialization-of-cvmat-objects-using-boost/)提供完整的资源. (4认同)
  • 这对于非连续矩阵不起作用,你实际上并不需要序列化`elem_size`,因为它是从矩阵的`type`派生的. (2认同)