c++ - Cargue eficientemente un tapete grande en la memoria en OpenCV
mat opencv3.0 (1)
¿Estás bien con una aceleración de 100x ?
Debe guardar y cargar sus imágenes en formato binario.
Puede hacerlo con la función
matwrite
y
matread
en el código a continuación.
FileStorage
tanto la carga desde un
FileStorage
como el archivo binario, y para una imagen más pequeña con 250K filas, 192 columnas, escriba
CV_8UC1
obtuve estos resultados (tiempo en ms):
// Mat: 250K rows, 192 cols, type CV_8UC1
Using FileStorage: 5523.45
Using Raw: 50.0879
En una imagen con 1M de filas y 192 cols usando el modo binario que obtuve (tiempo en ms):
// Mat: 1M rows, 192 cols, type CV_8UC1
Using FileStorage: (can''t load, out of memory)
Using Raw: 197.381
NOTA
- Nunca mida el rendimiento en la depuración .
-
3 minutos para cargar una matriz parece demasiado, incluso para
FileStorage
s. Sin embargo, ganarás mucho cambiando al modo binario.
Aquí el código con las funciones
matwrite
y
matread
, y la prueba:
#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;
}
¿Existe una forma más eficiente de cargar un objeto Mat grande en la memoria que el método FileStorage en OpenCV?
Tengo un tapete grande con 192 columnas y 1 millón de filas que quiero almacenar localmente en un archivo y cargar en la memoria, luego se inicia mi aplicación. No hay ningún problema al usar FileStorage, pero me preguntaba si existe un método más eficiente para hacerlo. Por el momento, tarda unos 5 minutos en cargar el Mat en la memoria usando el modo de depuración en Visual Studio y alrededor de 3 minutos en el modo de lanzamiento y el tamaño del archivo de datos es de alrededor de 1,2 GB.
¿Es el método FileStorage el único método disponible para realizar esta tarea?