在opencv c ++中保存多维矩阵

Posted

技术标签:

【中文标题】在opencv c ++中保存多维矩阵【英文标题】:Saving multi-dimensional matrix in opencv c++ 【发布时间】:2014-09-08 13:25:00 【问题描述】:

在 brunocodutra in his answer 的帮助下,我在 opencv、c++ 中创建了一个 3D 浮点矩阵。我的矩阵是1024*1024*N(N不是常数,可能会改变)

当我说const int N = some_number; 我可以说

typedef Vec<float,N> VecNf;

在这个类型定义之后,我可以玩矩阵了。但是,我不希望 N 保持不变,因此我被困在那里。我相信,应该有一些简单的解决方案,但我还找不到。

编辑:我添加了保存矩阵的代码。假设我正确地创建了具有 100 个通道的 3D Mat noise

typedef Vec<float,100> Vec100f;
void writeNoise_ND(string filename,Mat noise) throw()
    int chans = noise.channels();
    int sz = noise.rows;

    FILE* fp = fopen(filename.c_str(),"wb");
    if (!fp)
        perror("out directory is not found\n");
    
    float *buffer = new float[sz];

    for(int c = 0; c < chans; c++)
        for(int i=0;i<sz;++i)
            for(int j=0;j<sz;++j)
                buffer[j]=noise.at<Vec100f>(i,j)[c];
            fwrite(buffer,sizeof(Vec100f),sz,fp);
        
    

    fclose(fp);
    free(buffer);   

有人可以指导我吗?如果它已经被问到问题,对不起。

提前致谢,

【问题讨论】:

您能否详细说明“保存”部分?我想你的意思是声明。 我删除了我的答案,因为这显然不是你想要的。您的问题源于 Vec 的大小 N 是编译时常量。在我看来,您可以更改您的类型,以便 Mat::at 返回std::vector 而不是Vecstd::vector 的大小在编译时可能未知。另一种方法是编写一个包装器来序列化和反序列化您的 Mat。这样的函数可以在写入数据和每个维度的大小 + 通道数之前重塑 Mat。你需要一个互惠函数来读回它。 我没有得到包装部分。你能详细说明一下吗?是不是有vector&lt;Mat&gt; 而不是N dimensional Mat 【参考方案1】:

您的 Mat 似乎是我认为的具有 N 个通道的 2D Mat。就像典型的图像是 2D Mat 3 通道 (RGB)。以下代码将存储所有通道 0,然后是所有通道 1 等,直到通道 N-1:

#include <fstream>
#include <vector>

void writeNoise(string filename, Mat noise)

    int chans = noise.channels();
    int sz = noise.rows;  // should check that noise.cols is == noise.rows

    std::ofstream f(filename, ios::out | ios::binary);

    if (!f.is_open())
        throw std::ofstream::failure("out directory is not found\n");

    std::vector<float> buffer(sz);

    for(int c = 0; c < chans; c++)
    
        for(int i = 0; i < sz; ++i)
        
            float* p = noise.ptr<float>(i) + c;

            for(int j = 0; j < sz; ++j)
            
                buffer[j] = *p;
                p += chans;
            
            f.write((const char *) &buffer[0], sizeof(float) * buffer.size());
        
    

    f.close();

如果你想在 (row = 15, col = 15) 访问通道 15,假设你不知道编译时的通道数(所以你不能使用at()),你可以这样做这个;

float get(cv::Mat m, int row, int col, int chan)

    float* p = m.ptr<float>(row);
    return p[col * m.channels() + chan];    


/* ... */

cout << get(noise, 15, 15, 15) << endl;

请注意,将get() 用于顺序访问像素是不合适的(因为与我在writeNoise() 中那样访问像素相比,它会非常慢)

【讨论】:

这看起来不错,但为什么f.write((char *) &amp;buffer[0], sizeof(float) * buffer.size()); 中有(char *)?此外,访问元素仍然是一个问题吗?例如,我想打印出noise[15,15,15]th element,我将如何访问该元素? write() 接受const char * 参数,而&amp;buffer[0]float*,因此需要显式转换 - 我通过添加const 更正了我的答案。至于访问元素,这不是您的问题的一部分,但我在答案中添加了一种可能的方式。

以上是关于在opencv c ++中保存多维矩阵的主要内容,如果未能解决你的问题,请参考以下文章

使用 C++ 在 OpenCV 中的矩阵中的多维数据

如何在openCV中修改部分多维矩阵?

如何将opencv Mat矩阵保存到可以在Matlab中加载的文件中

如何在opencv中将图像转换为矩阵[重复]

c ++ opencv中的等价matlab代码

使用 C++ 在 OpenCV 中按深度维度排序