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
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];
}
}
}
You can get values in array like this:
double val = array+ (r*mat.step)+c*mat.channels()+ch;
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;
}