Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在OpenCV中高效地将大型Mat加载到内存中_C++_Opencv_Mat_Opencv3.0 - Fatal编程技术网

C++ 在OpenCV中高效地将大型Mat加载到内存中

C++ 在OpenCV中高效地将大型Mat加载到内存中,c++,opencv,mat,opencv3.0,C++,Opencv,Mat,Opencv3.0,有没有比OpenCV中的FileStorage方法更有效的方法将大型Mat对象加载到内存中 我有一个192列和100万行的大垫子,我想本地存储在一个文件中,然后加载到内存中,然后我的应用程序启动。使用文件存储没有问题,但我想知道是否有更有效的方法来实现这一点。目前,在Visual Studio中使用调试模式将Mat加载到内存大约需要5分钟,在发布模式下大约需要3分钟,数据文件的大小大约为1.2GB 文件存储方法是执行此任务的唯一可用方法吗?您是否可以使用100x加速 您应该以二进制格式保存和加

有没有比OpenCV中的FileStorage方法更有效的方法将大型Mat对象加载到内存中

我有一个192列和100万行的大垫子,我想本地存储在一个文件中,然后加载到内存中,然后我的应用程序启动。使用文件存储没有问题,但我想知道是否有更有效的方法来实现这一点。目前,在Visual Studio中使用调试模式将Mat加载到内存大约需要5分钟,在发布模式下大约需要3分钟,数据文件的大小大约为1.2GB

文件存储方法是执行此任务的唯一可用方法吗?

您是否可以使用100x加速


您应该以二进制格式保存和加载图像。您可以使用下面代码中的
matwrite
matread
功能来完成此操作

我测试了从
FileStorage
和二进制文件加载,对于一个250K行192列的较小图像,键入
CV_8UC1
我得到了以下结果(时间单位为ms):

在一个有1M行和192列的图像上,使用我得到的二进制模式(时间单位为ms):

注意

  • 永远不要在调试中测量性能
  • 3分钟加载一个矩阵似乎太多了,即使对于
    FileStorage
    s也是如此。然而,切换到二进制模式会获得很多好处
  • 这里是具有函数
    matwrite
    matread
    的代码,以及测试:

    #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;
    }
    
    #包括
    #包括
    #包括
    使用名称空间std;
    使用名称空间cv;
    无效matwrite(常量字符串和文件名,常量Mat和Mat)
    {
    流fs(文件名,fstream::binary);
    //标题
    int type=mat.type();
    int channels=mat.channels();
    fs.write((char*)&mat.rows,sizeof(int));//行
    fs.write((char*)&mat.cols,sizeof(int));//cols
    fs.write((char*)&type,sizeof(int));//type
    fs.write((char*)&channels,sizeof(int));//通道
    //资料
    if(mat.isContinuous())
    {
    fs.write(mat.ptr(0),(mat.dataend-mat.datastart));
    }
    其他的
    {
    int rowsz=CV元素尺寸(类型)*材料颜色;
    对于(int r=0;rcout存储通道输出有什么用?您在读回文件时似乎没有使用它。只是问,因为我的own@sturkmen1)我有这个版本的生产代码,我不想阻止它2)通道信息对于在matlab中加载图像非常有用3)节省一个字节没什么大不了的4)在没有通道的情况下更新代码非常容易;)
    
    // Mat: 1M rows, 192 cols, type CV_8UC1
    Using FileStorage: (can't load, out of memory)
    Using Raw:         197.381
    
    #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;
    }