【问题标题】:Sending Opencv Mat through a TCP connection in C++在 C++ 中通过 TCP 连接发送 Opencv Mat
【发布时间】:2015-06-03 13:41:01
【问题描述】:

我正在尝试通过 TCP 连接发送 OpenCv Mat。到目前为止,我能够在 boost::asio tutorial 之后建立一个简单的 TCP 连接。

我想知道我是否可以简单地修改该示例并将 cv::Mat image_ 代替 tcp 连接对象内的字符串 message_ ,或者我是否应该使用不同的策略向客户端提供图像.

【问题讨论】:

  • 使用 imencode() 将其编码为 jpg 或 png,然后通过网络发送
  • 那么我只需要将字符串message_替换为tcp_connection中的vector& image_encoded_?

标签: c++ sockets opencv boost tcp


【解决方案1】:

既然你已经在使用 Boost,不妨看看模块 serialization。下面是一个将cv::Mat 转换为std::string 的示例:

#include <opencv2/core.hpp>

#include <boost/serialization/split_free.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>

#include <cassert>
#include <string>
#include <vector>

BOOST_SERIALIZATION_SPLIT_FREE( cv::Mat )

namespace boost {
namespace serialization {

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

    ar & m.cols;
    ar & m.rows;
    ar & elemSize;
    ar & elemType;

    const size_t dataSize = m.cols * m.rows * m.elemSize();
    for ( size_t i = 0; i < dataSize; ++i )
        ar & m.data[ i ];
}


template <class Archive>
void load( Archive & ar, cv::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, static_cast< int >( elemType ) );
    const size_t dataSize = m.cols * m.rows * elemSize;
    for (size_t i = 0; i < dataSize; ++i)
        ar & m.data[ i ];
}

} // namespace serialization
} // namespace boost

std::string save( const cv::Mat & mat )
{
    std::ostringstream oss;
    boost::archive::text_oarchive toa( oss );
    toa << mat;

    return oss.str();
}

void load( cv::Mat & mat, const char * data_str )
{
    std::stringstream ss;
    ss << data_str;

    boost::archive::text_iarchive tia( ss );
    tia >> mat;
}

int main( int argc, char ** argv )
{
    cv::Mat eye = cv::Mat::eye( 3, 3, CV_32FC1 );

    std::string serialized = save( eye );
    std::cout << "serialized   = " << serialized << std::endl;

    cv::Mat deserialized;
    load( deserialized, serialized.c_str() );
    std::cout << "deserialized = \n\n" << deserialized << std::endl;

    return 0;
}

【讨论】:

  • 效率怎么样?我的意思是,将 Mat 序列化为字符串或使用 imencode 会更有效吗?
  • 很难说。尝试这两种建议,然后告诉我们您的里程数。
【解决方案2】:

试试这个来改进 cv::Mat 的序列化

template<class Archive>
void save(Archive & ar, const ::cv::Mat& m, const unsigned int version)
{
    int cols = m.cols;
    int rows = m.rows;
    size_t elem_size = m.elemSize();
    size_t elem_type = m.type();
    ar & cols;
    ar & rows;
    ar & elem_size;
    ar & elem_type;
    const size_t data_size = m.cols * m.rows * elem_size;

    boost::serialization::binary_object data(m.data, data_size);
    ar & data;
}

/** Serialization support for cv::Mat */
template<class Archive>
void load(Archive & ar, ::cv::Mat& m, const unsigned int version)
{
    int cols, rows;
    size_t elem_size, elem_type;
    ar & cols;
    ar & rows;
    ar & elem_size;
    ar & elem_type;
    m.create(rows, cols, elem_type);
    size_t data_size = m.cols * m.rows * elem_size;

    boost::serialization::binary_object data(m.data, data_size);
    ar & data;
}

boost::serialization::binary_object 数据可以处理二进制数据的序列化,性能要好得多。

【讨论】:

  • 这部分代码出现编译错误。我使用命令,g++ -std=c++11 server.cpp -o server `pkg-config --cflags --libs opencv4` -lboost_system -lboost_serialization
  • error: no member named 'binary_object' in namespace 'boost::serialization'; did you mean 'base_object'?
猜你喜欢
  • 2021-10-30
  • 2018-01-22
  • 1970-01-01
  • 1970-01-01
  • 2015-04-16
  • 1970-01-01
  • 1970-01-01
  • 2014-07-01
  • 1970-01-01
相关资源
最近更新 更多