在OpenCV中有效地将大的Mat加载到内存中
有没有比OpenCV中的FileStorage方法更有效的方法来加载一个大型的Mat对象?
我有一个大的垫子,192列,100万行,我想本地存储在一个文件,并加载到内存然后我的应用程序启动。 使用FileStorage没有问题,但我想知道是否存在一个更有效的方法来做到这一点。 目前,使用Visual Studio中的debugging模式将Mat放入内存大约需要5分钟,在Release模式下大约需要3分钟,数据文件大小约为1.2GB。
FileStorage方法是唯一可用于执行此任务的方法吗?
你可以100倍加速吗?
您应该保存并加载二进制格式的图像。 你可以用下面的代码中的matwrite
和matread
函数来实现。
我testing了从FileStorage
和二进制文件加载,并为250K行,192列, CV_8UC1
types的小图像我得到这些结果(以毫秒为单位):
// Mat: 250K rows, 192 cols, type CV_8UC1 Using FileStorage: 5523.45 Using Raw: 50.0879
在使用二进制模式的1M行和192列的图像上(时间以毫秒为单位):
// Mat: 1M rows, 192 cols, type CV_8UC1 Using FileStorage: (can't load, out of memory) Using Raw: 197.381
注意
- 不要在debugging中测量性能。
- 3分钟加载matrix似乎太多了,即使是
FileStorage
也是如此。 但是,您将会切换到二进制模式。
这里的函数matwrite
和matread
的代码,以及testing:
#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; }