当前位置: 首页 > 面试题库 >

OpenCV cv :: Mat到std :: ifstream用于base64编码

仲孙默
2023-03-14
问题内容

老实说,我很惊讶到目前为止还没有人遇到过这种情况。我正在将图片从OpenCV加载到cv :: Mat中,在通过套接字发送之前,我想对它进行base64编码。

对于base64,我使用的是libb64,因为它是Debian / Ubuntu的本机,并且易于使用且非常快速。编码函数将std :: ifstream作为参数,并输出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 :: Mat填充流。谷歌搜索,我发现我可以按列和行迭代cv :: Mat,并获取每个(我假设的像素)RGB值:

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

这是正确的做法吗?还有更优雅的方法吗?


问题答案:

为了能够通过HTTP发送图像,您还需要对其宽度,高度和类型进行编码。您需要将序列Mat化为流,并使用libb64对该流进行编码。另一方面,您需要解码该流并反序列化图像以检索它。

我实现了一个小型测试程序,该程序使用std::stringstream缓冲区来进行序列化和反序列化。我选择了它,因为它同时扩展std::istreamstd::ostream其libb64用途。

serialize函数将a序列cv::Mat化为a std::stringstream。在其中,我写了图像的宽度,高度,类型,缓冲区的大小以及缓冲区本身。

该deserialize功能相反。它读取缓冲区的宽度,高度,类型,大小以及缓冲区。它效率不高,因为它需要分配一个临时缓冲区以从字符串流中读取数据。此外,它需要克隆映像,以便它不依赖临时缓冲区,并且它将处理自己的内存分配。我敢肯定,通过进行一些修补,它可以变得更有效率。

主要功能加载图像,对其进行序列化,使用libb64对其进行编码,然后对其进行解码,对其进行反序列化并将其显示在窗口中。这应该模拟您要尝试执行的操作。

// 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);
}


 类似资料:
  • 正常的ASCII是正确的,但韩语字符不是。 所以我做了一个简单的程序来读取一个UTF-8文本文件并打印内容。 输出表示,字符在字符串、文字和文件中的编码是不同的。

  • 我正在用base64编码的PNG创建一个Blob。。。 我不知道我做错了什么,但是blob的内容是一些东西,但不是我想要的png。 thx提前... [更新] 我认为Base64生成的字节数。解码是可以的。文件大小为1003字节,解码也产生1003字节。 [更新2]以下是我谈论的来源:https://github.com/MikeMitterer/AndroidIconGenerator.DART

  • 我有很多PDF文件,我需要得到它的内容编码使用Base64。我有一个Akka应用程序,它以流的形式获取文件,并分发给许多工人来编码这些文件,并为每个文件返回字符串base64。我得到了一个编码的基本解决方案: 它工作,但我想知道什么将是最好的方式,我可以使用缓冲区编码文件,如果有一个更快的替代这一点。 我测试了一些其他方法,例如: null 任何投入都是很有帮助的。谢谢你!

  • 介绍 Base64编码是用64(2的6次方)个ASCII字符来表示256(2的8次方)个ASCII字符,也就是三位二进制数组经过编码后变为四位的ASCII字符显示,长度比原来增加1/3。 使用 String a = "伦家是一个非常长的字符串"; //5Lym5a625piv5LiA5Liq6Z2e5bi46ZW/55qE5a2X56ym5Liy String encode = Base64.en

  • Go提供了对base64编码和解码的内置支持 package main // 这种导入包的语法将默认的base64起了一个别名b64,这样 // 我们在下面就可以直接使用b64表示这个包,省点输入量 import b64 "encoding/base64" import "fmt" func main() { // 这里是我们用来演示编码和解码的字符串 data := "abc12

  • Base64编码将二进制数据转换为文本格式,通过通信通道传递,用户可以安全地处理文本。 Base64也称为Privacy enhanced Electronic mail (PEM) ,主要用于电子邮件加密过程。 Python包含一个名为BASE64的模块,它包括两个主要功能,如下所示 - base64.decode(input, output) - 它解码指定的输入值参数,并将解码的输出存储为对