C++ 如何在 OpenCV 中将 Float Mat 写入文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16312904/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 20:15:21  来源:igfitidea点击:

How to write a Float Mat to a file in OpenCV

c++opencvfile-iofloating-pointmat

提问by Karthik Murugan

I have a matrix

我有一个矩阵

Mat B(480,640,CV_32FC1);

Mat B(480,640,CV_32FC1);

containing floating values..I want to write this matrix to a file which could be opened in notepad or Ms word or Excel to see the values inside and for storage....imwrite functioncan save 8-bit or 16-bit image only..

包含浮动值..我想将此矩阵写入一个文件,该文件可以在记事本或 Ms word 或 Excel 中打开以查看内部和存储的值.... imwrite 函数只能保存 8 位或 16 位图像..

Drop in your suggestions if this could be done?? if yes, how ??

如果可以做到这一点,请提出您的建议?如果是,如何?

回答by sansuiso

Using pure OpenCV API calls:

使用纯 OpenCV API 调用:

// 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 xmlor 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

文件扩展名可以是xmlyml。在这两种情况下,您都会获得一个可以轻松删除/解析的小标题,然后您可以访问浮点格式的数据。我成功地使用了这种方法(使用 yml 文件)将数据导入 Matlab 和 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).
  1. 使用任何编辑器打开文件
  2. 然后抑制除数据标签内容(即像素值)之外的所有文本和数字。
  3. 完成后,使用 txt 或 csv 扩展名保存文件并使用 matlab 打开它(拖放工作)。

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

瞧。如果它没有正确猜测图像大小,您可能必须在 matlab 命令行中重塑结果矩阵。

回答by sgarizvi

You can write cv::Matto text file using simple C++ file handling.

您可以cv::Mat使用简单的 C++ 文件处理写入文本文件。

Here is how you can do it:

您可以这样做:

#include <iostream>
#include <fstream>

using namespace std;

void writeMatToFile(cv::Mat& m, const char* filename)
{
    ofstream fout(filename);

    if(!fout)
    {
        cout<<"File Not Opened"<<endl;  return;
    }

    for(int i=0; i<m.rows; i++)
    {
        for(int j=0; j<m.cols; j++)
        {
            fout<<m.at<float>(i,j)<<"\t";
        }
        fout<<endl;
    }

    fout.close();
}

int main()
{
    cv::Mat m = cv::Mat::eye(5,5,CV_32FC1);

    const char* filename = "output.txt";

    writeMatToFile(m,filename);

}

回答by John Smith

OpenCV can serialize (save) its objects in JSON, XMLor YAMLformats. You can use any editors, which understand these formats, in order to read these files, or use OpenCV to download data (de-serialize) from these files. Detailed explanation how this is done can be found here. In short, to store the data into xml-file, you have to call

OpenCV 可以以JSONXMLYAML格式序列化(保存)其对象。您可以使用任何能够理解这些格式的编辑器来读取这些文件,或者使用 OpenCV 从这些文件中下载数据(反序列化)。可以在此处找到如何完成此操作的详细说明。简而言之,要将数据存储到xml-file 中,您必须调用

cv::FileStorage fs("/path/to/file.xml", cv::FileStorage::WRITE); // create FileStorage object
cv::Mat cameraM; // matrix, which you need to save, do not forget to fill it with some data
fs << "cameraMatrix" << cameraM; // command to save the data
fs.release(); // releasing the file.

If you want to use JSONor YAML, just change the extension to .jsonor .yaml/.yml- openCV will automatically understand your intentions.

如果您想使用JSONor YAML,只需将扩展名更改为.jsonor .yaml/.yml- openCV 将自动理解您的意图。

The important thing is the command

重要的是命令

fs << "cameraMatrix" << cameraM;

the string "cameraMatrix"is the tag name, under which this matrix will be stored and using which this matrix can be found later in the file.

该字符串"cameraMatrix"是标签名称,该矩阵将存储在该标签名称下,稍后可以在文件中找到该矩阵。

Note that xmlformat will not allow you to use tag names with spaces and some special characters, since only alphanumeric values, dots, dashes and underscores are allowed (see XMLspecification for details), while in YAMLand JSONyou can have something like

请注意,xmlformat 不允许您使用带有空格和一些特殊字符的标签名称,因为只允许使用字母数字值、点、破折号和下划线(XML有关详细信息,请参阅规范),而在 in 中YAMLJSON您可以使用类似

fs << "Camera Matrix" << cameraM;

回答by Nadav B

I wrote this code:

我写了这段代码:

#include "opencv2/opencv.hpp"

using namespace cv;
using namespace std;

/*
Will save in the file:
cols\n
rows\n
elemSize\n
type\n
DATA
*/
void serializeMatbin(cv::Mat& mat, std::string filename){
    if (!mat.isContinuous()) {
        std::cout << "Not implemented yet" << std::endl;
        exit(1);
    }

    int elemSizeInBytes = (int)mat.elemSize();
    int elemType        = (int)mat.type();
    int dataSize        = (int)(mat.cols * mat.rows * mat.elemSize());

    FILE* FP = fopen(filename.c_str(), "wb");
    int sizeImg[4] = {mat.cols, mat.rows, elemSizeInBytes, elemType };
    fwrite(/* buffer */ sizeImg, /* how many elements */ 4, /* size of each element */ sizeof(int), /* file */ FP);
    fwrite(mat.data, mat.cols * mat.rows, elemSizeInBytes, FP);
    fclose(FP);
}

cv::Mat deserializeMatbin(std::string filename){
    FILE* fp = fopen(filename.c_str(), "rb");
    int header[4];
    fread(header, sizeof(int), 4, fp);
    int cols            = header[0]; 
    int rows            = header[1];
    int elemSizeInBytes = header[2];
    int elemType        = header[3];

    //std::cout << "rows="<<rows<<" cols="<<cols<<" elemSizeInBytes=" << elemSizeInBytes << std::endl;

    cv::Mat outputMat = cv::Mat::ones(rows, cols, elemType);

    size_t result = fread(outputMat.data, elemSizeInBytes, (size_t)(cols * rows), fp);

    if (result != (size_t)(cols * rows)) {
        fputs ("Reading error", stderr);
    }

    std::cout << ((float*)outputMat.data)[200] << std::endl;
    fclose(fp);
    return outputMat;
}

void testSerializeMatbin(){
    cv::Mat a = cv::Mat::ones(/*cols*/ 10, /* rows */ 5, CV_32F) * -2;
    std::string filename = "test.matbin";
    serializeMatbin(a, filename);
    cv::Mat b = deserializeMatbin(filename);
    std::cout << "Rows: " << b.rows << " Cols: " << b.cols << " type: " << b.type()<< std::endl;
}

回答by michael scheinfeild

use write binary :

使用写入二进制文件:

FILE* FP = fopen("D.bin","wb");
    int sizeImg[2] = { D.cols , D.rows };
    fwrite(sizeImg, 2, sizeof(int), FP);
    fwrite(D.data, D.cols * D.rows, sizeof(float), FP);
    fclose(FP);

then you can read in in matlab read size and then reshape (type=single)

然后您可以在matlab读取大小中读取然后重塑(类型=单个)

fp=fopen(fname);
data=fread(fp,2,'int');
width = data(1); height = data(2);
B = fread(fp,Inf,type);

imageOut = reshape(B,[width,height])';

fclose(fp);