OpenCV的CV ::垫到std ::为Base64编码的ifstream [英] OpenCV cv::Mat to std::ifstream for base64 encoding

查看:1782
本文介绍了OpenCV的CV ::垫到std ::为Base64编码的ifstream的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说实话,我惊讶没有人迄今已运行到这一点。
我加载图片来自OpenCV的成 CV ::垫,我想为Base64 EN code之前,我通过套接字发送出去。

To be honest I'm suprised nobody has run into this thus far. I'm loading a picture from OpenCV into cv::Mat, which I want to base64 encode before I send it over a socket.

有关的base64我使用 libb64 ,因为它是原生的Debian / Ubuntu和易于使用,并且非常快。该编码功能作为一个参数一个的std :: ifstream的,然后输出的std ::的ofstream

For base64 I am using libb64 as it is native to Debian/Ubuntu, and easy to use and very fast. The encoding function takes as a parameter an std::ifstream, and outputs an std::ofstream.

#include <opencv2/opencv.hpp>
#include <b64/encode.h>
#include <fstream>

using namespace cv;
Mat image;
image = imread( "picture.jpg", CV_LOAD_IMAGE_COLOR );

if ( image.data )
{
    std::ifstream instream( ???, std::ios_base::in | std::ios_base::binary);
    std::ofstream outstream;        

    // Convert Matrix to ifstream
    // ...

    base64::encoder E;
    E.encode( instream, outstream );

    // Now put it in a string, and send it over a socket...
}

我真的不知道如何从CV填充河道::垫。
周围的Googling,我发现我可以遍历简历::垫,通过行和列,并得到各(像素我假设)RGB值:

I don't really know how to populate the instream from the cv::Mat. Googling around, I found that I can iterate a cv::Mat, by columns and rows, and get each (pixel I am assuming) RGB values:

for ( int j = 0; j < image.rows; j++ )
{
    for ( int i = 0; i < image.cols; i++ )
    {
        unsigned char b = input [ image.step * j + i ] ;
        unsigned char g = input [ image.step * j + i + 1 ];
        unsigned char r = input [ image.step * j + i + 2 ];
    }
}

这是怎么回事呢它的正确方法?有一些更优雅的方式?

Is this the right way of going on about it? Is there some more elegant way?

推荐答案

在为了能够通过HTTP发送图像,还需要连接code的宽度,高度和类型。您需要将序列化到一个流和连接code与libb64流。在另一边,你需要去code,它流和反序列化的图像进行检索。

In order to be able to send an image via HTTP, you also need to encode its width, height and type. You need to serialize the Mat into a stream and encode that stream with libb64. On the other side you need to decode that stream and deserialize the image to retrieve it.

我实现了一个小的测试程序,它使用的std :: stringstream的作为缓冲这种序列化和反序列化。我选择了它,因为它同时扩展的std :: istream的的std :: ostream的这libb64用途。

I implemented a small test program that does this serialization and deserialization using std::stringstream as a buffer. I chose it because it extends both std::istream and std::ostream which libb64 uses.

连载函数串行化一个 CV ::垫的std :: stringstream的。在这里面,我写的图像的宽度,高度,类型,缓冲和缓冲器本身的大小。

The serialize function serializes a cv::Mat into a std::stringstream. In it, I write the image width, height, type, size of the buffer and the buffer itself.

反序列化功能正好相反。它读取宽度,高度,类型,缓冲和缓冲区的大小。它的效率不高,因为它可能是因为它需要分配一个临时缓冲区来读取stringstream的数据。另外,它需要克隆的图像,使得它不依赖于暂时缓冲器,这将处理其自己的内存分配。我敢肯定,随着一些修补,可以更有效率。

The deserialize function does the reverse. It reads the width, height, type, size of the buffer and the buffer. It's not as efficient as it could be because it needs to allocate a temporary buffer to read the data from the stringstream. Also, it needs to clone the image so that it does not rely on the temporary buffer and it will handle its own memory allocation. I'm sure that with some tinkering it can be made more efficient.

主要功能加载一个图像,使用libb64其序列,连接codeS,然后去codeS了,反序列化并将其显示在一个窗口。这应该模拟一下你正在尝试做的。

The main function loads an image, serializes it, encodes it using libb64, then decodes it, deserializes it and displays it in a window. This should simulate what you are trying to do .

// Serialize a cv::Mat to a stringstream
stringstream serialize(Mat input)
{
    // We will need to also serialize the width, height, type and size of the matrix
    int width = input.cols;
    int height = input.rows;
    int type = input.type();
    size_t size = input.total() * input.elemSize();

    // Initialize a stringstream and write the data
    stringstream ss;
    ss.write((char*)(&width), sizeof(int));
    ss.write((char*)(&height), sizeof(int));
    ss.write((char*)(&type), sizeof(int));
    ss.write((char*)(&size), sizeof(size_t));

    // Write the whole image data
    ss.write((char*)input.data, size);

    return ss;
}

// Deserialize a Mat from a stringstream
Mat deserialize(stringstream& input)
{
    // The data we need to deserialize
    int width = 0;
    int height = 0;
    int type = 0;
    size_t size = 0;

    // Read the width, height, type and size of the buffer
    input.read((char*)(&width), sizeof(int));
    input.read((char*)(&height), sizeof(int));
    input.read((char*)(&type), sizeof(int));
    input.read((char*)(&size), sizeof(size_t));

    // Allocate a buffer for the pixels
    char* data = new char[size];
    // Read the pixels from the stringstream
    input.read(data, size);

    // Construct the image (clone it so that it won't need our buffer anymore)
    Mat m = Mat(height, width, type, data).clone();

    // Delete our buffer
    delete[]data;

    // Return the matrix
    return m;
}

void main()
{
    // Read a test image
    Mat input = imread("D:\\test\\test.jpg");

    // Serialize the input image to a stringstream
    stringstream serializedStream = serialize(input);

    // Base64 encode the stringstream
    base64::encoder E;
    stringstream encoded;
    E.encode(serializedStream, encoded);

    // Base64 decode the stringstream
    base64::decoder D;
    stringstream decoded;
    D.decode(encoded, decoded);

    // Deserialize the image from the decoded stringstream
    Mat deserialized = deserialize(decoded);

    // Show the retrieved image
    imshow("Retrieved image", deserialized);
    waitKey(0);
}

这篇关于OpenCV的CV ::垫到std ::为Base64编码的ifstream的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆