Слияние нескольких форсированных сериализованных матов OpenCV

Ответьте на вопрос здесь о сериализации OpenCV Mat_

Моя задача - у меня есть несколько сериализованных матов OpenCV. Теперь я хочу объединить все эти маты. Я могу сделать это, десериализуя эти двоичные файлы в Mats и используя метод push_back для их объединения. Однако по моей собственной причине я должен сначала объединить их в двоичном формате, прежде чем десериализовать.

Как я могу объединить эти двоичные файлы, чтобы в конце концов я мог вызвать ту же десериализацию, чтобы получить весь большой Mat?

Спасибо


person user3685928    schedule 19.07.2016    source источник


Ответы (1)


Вы можете сделать это без использования boost. Следуя подходу сериализации, описанному здесь, вы можете добавить данные своей матрицы в конец файла, позаботившись об увеличении количество строк итоговой матрицы соответственно.

Вот рабочий пример, где matappend выполняет свою работу. Я также добавлю функции matread и matwrite для полноты:

#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;
}
person Miki    schedule 20.07.2016