Ahsan Iqbal
Ahsan Iqbal

Reputation: 1432

Opencv in memory Mat representation

I know that in memory opencv represents Mat objects as one big array. So if I have 3 channels mat of dimension 200x200 then In memory it will store this mat in an array of size 3x200x200. Or more generally any Mat in memory will be stored as channels*rows*cols. We can get such array as

double *array = (double)mat.data;

assuming that matrix is of type double

Now my question is what is the way to index this array for instance if I want to access element at channel ch, row r and col c is following is valid indexing

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

or

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

Regards Ahsan

Upvotes: 11

Views: 12074

Answers (4)

J.Zhao
J.Zhao

Reputation: 2330

I think this official link will help you!

For RGB type image:

RGB image in memory

Upvotes: 2

Gianni
Gianni

Reputation: 518

I found other answers a bit confusing: mat.step is the size of a row in bytes, not in (double) elements, and it does already take into consideration the number of channels. To access val you should use:

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

You can verify this and other approaches comparing them with the .at<> operator as follows:

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

Upvotes: 1

Miki
Miki

Reputation: 41765

As you can see in the data layout reported on the documentation, you can access the values like:

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

Upvotes: 10

IvoLiu
IvoLiu

Reputation: 41

You can get values in array like this:

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

Upvotes: 1

Related Questions