2016-12-17 8 views
1

Как и в названии, у меня есть std::vector<cv::Mat> matrices, который я хочу написать/прочитать в/из двоичного файла.Напишите вектор cv :: Mat для двоичного файла в C++

Теперь, после this ответа, все, что я должен сделать для Сочинения:

ofstream fout("matrices.bin", ios::out | ios::binary); 
size_t size = matrices.size(); 
fout.write((char*)&size, sizeof(size)); 
fout.write((char*)&matrices[0], v.size() * sizeof(cv::Mat)); 
fout.close(); 

Однако после this ответа, писать cv::Mat объектов, кажется, немного сложнее, и в ответе matRead и matWrite сделать работа. Так интересно, если вместо кода выше, я должен сделать что-то вроде:

ofstream fout("matrices.bin", ios::out | ios::binary); 
size_t size = matrices.size(); 
fout.write((char*)&size, sizeof(size)); 
for(size_t i = 0 ; i < matrices.size() ; i++) 
    matWrite("matrices.bin", matrices[i]); 

Однако этот код не работает, так как matWrite() перезаписывает matrices.bin в каждом цикле, так что я должен добавить размер matrices[i], как смещение перед записью самой матрицы.

Что мне делать?

UPDATE:

Я пришел к этому решению, переписывание matWrite и matRead с дополнительными аргументами для добавления матрицы во время записи и начать читать с определенной точки:

void matwrite(const std::string& filename, const cv::Mat& mat, const bool append = false) { 

    std::ofstream fs; 
    if(append) 
     fs.open(filename.c_str(), std::fstream::binary | std::fstream::app); 
    else 
     fs.open(filename.c_str(), std::fstream::binary); 

//the rest of matwrite is the same... 

} 

cv::Mat matRead(const std::string& filename, size_t &offset = 0) 
{ 
    std::ifstream fs(filename, std::fstream::binary); 
    fs.seekg(offset); 
    ... 
    offset += 4 * sizeof(int) + CV_ELEM_SIZE(type) * rows * cols; //update offset //move offset of 4 ints and mat size 
    return mat; 
} 

и функции вызванный с:

//writing: 
for(size_t i = 0 ; i<v.size() ; i++) 
    writemat(filename, v[i], true); 
//reading: 
size_t offset = 0; 
for(size_t i = 0 ; i<size ; i++){ // size = v.size() during writing 
    cv::Mat mat = matRead(filename, offset); 
    v.push_back(mat); 
} 
+0

Я действительно интересно знать, почему кто-то дал мне downvote для этого Questio – justHelloWorld

+0

записку о дубликате. Вы можете перебирать каждую матрицу в своем векторе и использовать «matappend». – Miki

+0

Если дубликат не помогает, дайте мне знать. Однако теперь вы должны иметь возможность написать правильную функцию самостоятельно – Miki

ответ

1

Вы можете адаптировать код от matread and matwrite для использования с векторами, если Mat, вместо одного Mat. Функции vecmatread и vecmatwrite ниже позволяют написать std::vector<cv::Mat> в файл и читать вектор обратно:

#include <opencv2\opencv.hpp> 
#include <vector> 
#include <iostream> 
#include <fstream> 

using namespace std; 
using namespace cv; 

void vecmatwrite(const string& filename, const vector<Mat>& matrices) 
{ 
    ofstream fs(filename, fstream::binary); 

    for (size_t i = 0; i < matrices.size(); ++i) 
    { 
     const Mat& mat = matrices[i]; 

     // 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); 
      } 
     } 
    } 
} 

vector<Mat> vecmatread(const string& filename) 
{ 
    vector<Mat> matrices; 
    ifstream fs(filename, fstream::binary); 

    // Get length of file 
    fs.seekg(0, fs.end); 
    int length = fs.tellg(); 
    fs.seekg(0, fs.beg); 

    while (fs.tellg() < length) 
    { 
     // 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); 

     matrices.push_back(mat); 
    } 
    return matrices; 
} 


int main() 
{ 
    vector<Mat> matrices; 

    // Fill vector... 
    Mat1f m1(3,3); 
    randu(m1, 0, 1); 

    Mat3b m2(4, 5); 
    randu(m2, Scalar(0,0,0), Scalar(256,256,256)); 

    Mat2d m3(2, 3); 
    randu(m3, Scalar(0, 0), Scalar(1, 1)); 

    matrices.push_back(m1); 
    matrices.push_back(m2); 
    matrices.push_back(m3); 

    // Write the vector to file 
    vecmatwrite("test.bin", matrices); 

    // Read the vector from file 
    vector<Mat> matrices2 = vecmatread("test.bin"); 

    return 0; 
}