c++保存及读取文件
1.保存及读取单张图片
代码中给出了两种方法,一种是opencv
自带的FileStorage
,另一种是使用c++
原生的fstream
实现。代码验证fstream
方式更快。
#include <opencv2\opencv.hpp>
#include <iostream>
#include <fstream>
using namespace std;
using namespace cv;
void matwrite(const string& filename, const Mat& mat)
{
ofstream fs(filename, fstream::binary);
// Header
int type = mat.type();
int channels = mat.channels();
fs.write((char*)&mat.rows, sizeof(int)); // rows
fs.write((char*)&mat.cols, sizeof(int)); // cols
fs.write((char*)&type, sizeof(int)); // type
fs.write((char*)&channels, sizeof(int)); // channels
// Data
if (mat.isContinuous())
{
fs.write(mat.ptr<char>(0), (mat.dataend - mat.datastart));
}
else
{
int rowsz = CV_ELEM_SIZE(type) * mat.cols;
for (int r = 0; r < mat.rows; ++r)
{
fs.write(mat.ptr<char>(r), rowsz);
}
}
}
Mat matread(const string& filename)
{
ifstream fs(filename, fstream::binary);
// Header
int rows, cols, type, channels;
fs.read((char*)&rows, sizeof(int)); // rows
fs.read((char*)&cols, sizeof(int)); // cols
fs.read((char*)&type, sizeof(int)); // type
fs.read((char*)&channels, sizeof(int)); // channels
// Data
Mat mat(rows, cols, type);
fs.read((char*)mat.data, CV_ELEM_SIZE(type) * rows * cols);
return mat;
}
int main()
{
// Save the random generated data
{
Mat m(1024*256, 192, CV_8UC1);
randu(m, 0, 1000);
FileStorage fs("fs.yml", FileStorage::WRITE);
fs << "m" << m;
matwrite("raw.bin", m);
}
// Load the saved matrix
{
// Method 1: using FileStorage
double tic = double(getTickCount());
FileStorage fs("fs.yml", FileStorage::READ);
Mat m1;
fs["m"] >> m1;
double toc = (double(getTickCount()) - tic) * 1000. / getTickFrequency();
cout << "Using FileStorage: " << toc << endl;
}
{
// Method 2: usign raw binary data
double tic = double(getTickCount());
Mat m2 = matread("raw.bin");
double toc = (double(getTickCount()) - tic) * 1000. / getTickFrequency();
cout << "Using Raw: " << toc << endl;
}
int dummy;
cin >> dummy;
return 0;
}
2.保存及读取多张图片
void matwrite(const string& filename, vector<string>& imgFiles)
{
ofstream fs(filename, fstream::binary);
int num = imgFiles.size();
fs.write((char*)&num, sizeof(int)); // img number
for (auto& imgFile : imgFiles)
{
cout << imgFile << endl;
cv::Mat mat = cv::imread(imgFile, -1);
// Header
//int nameLen = sizeof(char)* imgFile.size();
int type = mat.type();
int channels = mat.channels();
//fs.write((char*)&nameLen, sizeof(int)); // name length
fs << imgFile << std::endl;
fs.write((char*)&mat.rows, sizeof(int)); // rows
fs.write((char*)&mat.cols, sizeof(int)); // cols
fs.write((char*)&type, sizeof(int)); // type
fs.write((char*)&channels, sizeof(int)); // channels
// Data
if (mat.isContinuous())
fs.write(mat.ptr<char>(0), (mat.dataend - mat.datastart));
else
{
int rowsz = CV_ELEM_SIZE(type) * mat.cols;
for (int r = 0; r < mat.rows; ++r)
fs.write(mat.ptr<char>(r), rowsz);
}
}
fs.close();
}
void matread(const string& datName,map<string,cv::Mat>& matDic)
{
ifstream fs(datName, fstream::binary);
int num;
fs.read((char*)&num, sizeof(int)); // img number
for (int i = 0; i < num; i++)
{
// Header
int nameLen,rows, cols, type, channels;
string fileName="";
//fs.read((char*)&nameLen, sizeof(int)); // rows
//cout << "nameLen: " << nameLen << endl;
getline(fs, fileName);
cout << "fileName: " << fileName << endl;
//fs.read((char*)&fileName, sizeof(char) * nameLen); // channels
fs.read((char*)&rows, sizeof(int)); // rows
fs.read((char*)&cols, sizeof(int)); // cols
fs.read((char*)&type, sizeof(int)); // type
fs.read((char*)&channels, sizeof(int)); // channels
// Data
cv::Mat mat(rows, cols, type);
fs.read((char*)mat.data, CV_ELEM_SIZE(type) * rows * cols);
matDic[fileName] = mat;
}
fs.close();
}
主程序为:
string path = "./img";
vector<string> imgFiles;
getFiles(path, imgFiles);
matwrite("mat.bin", imgFiles);
map<string, cv::Mat> matDic;
matread("mat.bin", matDic);
将图片保存为字典类型(图片名称+图片数据)。