首页 文章

Opencv在内存中的Mat表示

提问于
浏览
4

我知道在内存中opencv将Mat对象表示为一个大数组 . 因此,如果我有3个尺寸为200x200的通道垫,那么在内存中它会将这个垫存储在3x200x200大小的数组中 . 或者更常见的是,内存中的任何Mat都将存储为 channels*rows*cols . 我们可以得到这样的数组

double *array = (double)mat.data;

假设矩阵是double类型

现在我的问题是,如果我想访问通道ch中的元素,行r和col c以下是有效的索引,那么索引此数组的方法是什么?

array[ch*rows*cols + c * rows + r]

要么

array[ch*rows*cols + r * cols + c]

关心Ahsan

3 回答

  • 0

    正如您在documentation上报告的数据布局中所看到的,您可以访问以下值:

    for(int r=0; r<rows; ++r){
        for(int c=0; c<cols; ++c){
            for(int ch=0; ch<nchannels; ++ch){
                double val = array[(nchannels*mat.step*r) + (nchannels*c) + ch];
            }
        }
    }
    
  • 4

    您可以像这样获取数组中的值:

    double val = array+ (r*mat.step)+c*mat.channels()+ch;
    
  • 1

    我发现其他答案有点令人困惑: mat.step 是以字节为单位的行的大小,而不是(双)元素,并且它已经考虑了通道的数量 . 要访问val,您应该使用:

    double* array = (double*) mat.data; // was (double) mat.data in the question
    double value = array[ ((mat.step)/mat.elemSize1())*c+mat.channels()*r+ch]; // (mat.step)/mat.elemSize1() is the actual row length in (double) elements
    

    您可以验证此方法和其他方法,将它们与 .at<> 运算符进行比较,如下所示:

    #include <iostream>
    #include <opencv2/core.hpp>
    
    using namespace cv;
    using namespace std;
    
    int main()
    {
    const int w0=5;
    const int h=3;
    const int w=4;
    double data[w0*h*3];
    for (int y=0; y<h; y++)
        for (int x=0; x<w0; x++)
            for (int ch=0; ch<3; ch++)
                data[3*(x+w0*y)+ch]=1000+100*(y)+10*(x)+ch;
    
    Mat m0(h,w0,CV_64FC3, data);
    Rect roi(0,0,w,h);
    Mat mat=m0(roi);
    
    int c=3, r=2, ch=1;
    Vec3d v = mat.at<Vec3d>(r,c);
    cout<<"the 3 channels at row="<<r<<", col="<<c<<": "<<v<<endl;
    double* array= (double*) mat.data;
    double expect = 1000+100*r+10*c+ch;
    double value= array[ ((mat.step)/mat.elemSize1())*r+mat.channels()*c+ch];
    cout<<"row="<<r<<", col="<<c<<", ch="<<ch<<": expect="<<expect<<", value="<<value<<endl;
    return  0;
    }
    

相关问题