2015-09-01 23 views
13

Czy istnieje skuteczniejszy sposób załadowania dużego obiektu Mat do pamięci niż metoda FileStorage w OpenCV?Skutecznie ładuje dużą Matę do pamięci w OpenCV

Mam dużą matę z 192 kolumnami i milionem wierszy, które chcę przechowywać lokalnie w pliku i ładować do pamięci, a następnie uruchamia się moja aplikacja. Nie ma problemu z korzystaniem z FileStorage, ale zastanawiałem się, czy istnieje skuteczniejsza metoda, aby to zrobić. W tej chwili zajmuje około 5 minut załadowanie Mat do pamięci przy użyciu trybu debugowania w programie Visual Studio i około 3 minuty w trybie Release, a rozmiar pliku danych wynosi około 1,2 GB.

Czy metoda FileStorage jest jedyną dostępną metodą wykonywania tego zadania?

Odpowiedz

21

Czy jesteś w porządku z przyspieszeniem 100x?


Powinieneś zapisywać i ładować swoje obrazy w formacie binarnym. Możesz to zrobić za pomocą funkcji matwrite i matread w poniższym kodzie.

Testowałem zarówno załadunek od A FileStorage oraz plik binarny, a dla mniejszego obrazu z 250K wierszy, 192 kolumn, rodzaj CV_8UC1 Mam wyniki te (czas w ms):

// Mat: 250K rows, 192 cols, type CV_8UC1 
Using FileStorage: 5523.45 
Using Raw:   50.0879  

Na obrazie 1M wierszy i 192 cols używając trybu binarnego mam (czas w ms):

// Mat: 1M rows, 192 cols, type CV_8UC1 
Using FileStorage: (can't load, out of memory) 
Using Raw:   197.381 

UWAGA

  1. Nigdy nie mierz wydajności w debugowaniu.
  2. 3 minuty, aby załadować matrycę wydaje się zbyt wiele, nawet dla FileStorage s. Jednak wiele zyskasz przełączając się w tryb binarny.

Oto kod z funkcjami matwrite i matread i testu:

#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; 
} 
+1

co jest wykorzystanie przechowywania wyjście kanałów? wydaje się, że nie używasz go podczas odczytu pliku. Tylko pytam, ponieważ mam problemy z podobną funkcją mojego własnego. – Neal

+0

Och ... Masz rację; D. Zapomniałem usunąć tę linię ... – Miki

+0

@Miki dlaczego nie zaktualizujesz odpowiedzi – sturkmen