When we access specific elements of a cv::Mat structure, we can use mat.at(i,j) to access the element at position i,j. What is not immediately clear, however, whether (i,j) refers to the x,y coordinate in the matrix, or the ith row and the jth column.
OpenCV stores the data in row-major order in memory (i.e. the rows come first), while for example Matlab stores the data in column-major order in memory.
In OpenCV the main matrix class is called Mat and is contained in the OpenCV-namespace cv. This matrix is not templated but nevertheless can contain different data types. These are indicated by a certain type-number. Additionally, OpenCV provides a templated class called Mat_, which is derived from Mat.
The Mat class of OpenCV library is used to store the values of an image. It represents an n-dimensional array and is used to store image data of grayscale or color images, voxel volumes, vector fields, point clouds, tensors, histograms, etc.
CV_32F defines the depth of each element of the matrix, while. CV_32FC1 defines both the depth of each element and the number of channels.
So OpenCV handles this a bit strange. OpenCV stores the Mat in row major order, but addressing it over the methood Mat::at() falsely suggests column major order. I think the Opencv documentation is misleading in this case. I had to write this testcase to make sure for myself.
cv::Mat m(3,3,CV_32FC1,0.0f); m.at<float>(1,0) = 2; cout << m << endl;
So addressing is done with Mat::at(y,x) :
[0, 0, 0;
2, 0, 0;
0, 0, 0]
But raw pointer access reveals that it is actually stored row major, e.g. the "2" is in the 4th position. If it were stored in column major order, it would be in the 2nd position.
float* mp = &m.at<float>(0); for(int i=0;i<9;i++) cout << mp[i] << " ";
0 0 0 2 0 0 0 0 0
As a side remark: Matlab stores and addresses a matrix in column major order. It might be annoying, but at least it is consistent.
OpenCV, like many other libraries, treat matrix access in row-major order. That means every access is defined as (row, column)
. Note that if you're working with x and y coordinates of an image, this becomes (y, x)
, if y
is your vertical axis.
Most matrix libraries are the same in that regards, the access is (row, col)
as well in, for example, Matlab or Eigen (a C++ matrix library).
Where these applications and libraries do differ however is how the data is actually stored in memory. OpenCV stores the data in row-major order in memory (i.e. the rows come first), while for example Matlab stores the data in column-major order in memory. But if you're just a user of these libraries, and accessing the data via a (row, col)
accessor, you'll never actually see this difference in memory storage order.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With