2016-07-19 23 views
0

跟進序列化的OpenCV Mat_合併幾個升壓系列化的OpenCV墊

我的任務問題here是我有多個OpenCV的墊是序列化。現在我想合併所有的墊子。我可以通過將這些二進制文件反序列化爲Mats並使用push_back方法來合併它們。但是,出於我自己的原因,我必須在反序列化之前先以二進制格式合併它們。

如何合併這些二進制文件,以便最終可以調用相同的反序列化來獲取整個大的文件?

感謝

回答

1

你可以做到這一點,而無需使用提升。按照here描述的序列化方法,您可以在文件末尾添加矩陣的數據,從而相應地增加最終矩陣的行數。

下面是一個工作示例,其中matappend完成這項工作。我也會把matreadmatwrite功能完整性:

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

void matappend(const string& filename, const Mat& mat) 
{ 
    fstream fs(filename, fstream::binary | fstream::in); 

    // https://stackoverflow.com/a/2390938/5008845 
    if (fs.peek() == fstream::traits_type::eof()) 
    { 
     // The file is empty, write (same as matwrite) 

     fs.close(); 
     fs.open(filename, fstream::binary | fstream::out); 

     // 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 
    } 
    else 
    { 
     // The file is not empty, append 

     fs.close(); 
     fs.open(filename, fstream::binary | fstream::out | fstream::in); 

     // Read 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 

     // Consistency check 
     CV_Assert((cols == mat.cols) && (type == mat.type()) && (channels == mat.channels())); 

     // Go to beginning of file 
     fs.seekp(fstream::beg); 

     // Overwrite the number of rows 
     rows += mat.rows; 
     fs.write((char*)&rows, sizeof(int)); // rows 

     // Go to end of file 
     fs.seekp(0, fstream::end); 
    } 

    // Write data 
    if (mat.isContinuous()) 
    { 
     fs.write(mat.ptr<char>(0), (mat.dataend - mat.datastart)); 
    } 
    else 
    { 
     int rowsz = CV_ELEM_SIZE(mat.type()) * mat.cols; 
     for (int r = 0; r < mat.rows; ++r) 
     { 
      fs.write(mat.ptr<char>(r), rowsz); 
     } 
    } 
    fs.close(); 
} 



int main() 
{ 
    // Save the random generated data 

    Mat1b m1 = (Mat1b(2, 2) << 1, 2, 3, 4); 
    Mat1b m2 = (Mat1b(3, 2) << 5, 6, 7, 8, 9, 10); 

    matappend("raw.bin", m1); 
    matappend("raw.bin", m2); 

    Mat m3 = matread("raw.bin"); 

    // m3: 
    // 1 2 
    // 3 4 
    // 5 6 
    // 7 8 
    // 9 10 


    return 0; 
}