我有一个矩阵,
Mat B(480,640,CV_32FC1);
其中包含浮点数值。我想将这个矩阵写入一个文件,可以在记事本或Microsoft Word或Excel中打开以查看内部的值并进行存储,但是imwrite函数只能保存8位或16位图像...
这可行吗?如果可以,怎么做?
我有一个矩阵,
Mat B(480,640,CV_32FC1);
其中包含浮点数值。我想将这个矩阵写入一个文件,可以在记事本或Microsoft Word或Excel中打开以查看内部的值并进行存储,但是imwrite函数只能保存8位或16位图像...
这可行吗?如果可以,怎么做?
// Declare what you need
cv::FileStorage file("some_name.ext", cv::FileStorage::WRITE);
cv::Mat someMatrixOfAnyType;
// Write to file!
file << "matName" << someMatrixOfAnyType;
// Close the file and release all the memory buffers
file.release();
file << "matName" << someMatrixOfAnyType
;否则,你将会得到这个错误:OpenCV Error: Unspecified error (No element name has been given) in operator<<, file /usr/local/include/opencv2/core/operations.hpp, line 2910
。 - Daniel Goldenfile.release()
。作为一个经验法则,关闭和释放文件IO资源是很好的做法。 - dev_nutfile.release()
。否则,它不会保存实际数据。 - WhaSukGOfile.release()
。否则,它将不会保存实际数据。 - WhaSukGO您可以使用简单的C++文件处理将cv::Mat
写入文本文件。
以下是您可以执行此操作的方式:
#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);
}
OpenCV可以将其对象序列化(保存)为JSON、XML或YAML格式。您可以使用任何理解这些格式的编辑器来读取这些文件,或使用OpenCV从这些文件中下载数据(反序列化)。如何完成此操作的详细说明可以在此处找到。简而言之,要将数据存储到XML文件中,您需要调用
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.
.json
或.yaml/.yml
- OpenCV会自动理解您的意图。fs << "cameraMatrix" << cameraM;
"cameraMatrix"
是标签名称,此矩阵将存储在该标签下,并且可以使用该标签在文件中查找此矩阵。
请注意,xml
格式不允许您使用带有空格和某些特殊字符的标签名称,因为只允许字母数字值、点、破折号和下划线(详见XML
规范),而在YAML
和JSON
中,您可以使用如下内容:
fs << "Camera Matrix" << cameraM;
#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;
}
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);
然后你可以在MATLAB中读取它。
读取大小,然后重新整形(类型=single):
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);