Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing elements of a cv::Mat with at<float>(i, j). Is it (x,y) or (row,col)?

Tags:

c++

opencv

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.

like image 564
Chris Avatar asked Nov 18 '11 14:11

Chris


People also ask

Is OpenCV row or column major?

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.

What is a CV :: mat?

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.

What is mat type in OpenCV?

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.

What is CV_32FC1?

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.


2 Answers

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.

like image 38
Insa Avatar answered Oct 06 '22 00:10

Insa


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.

like image 98
Ela782 Avatar answered Oct 06 '22 01:10

Ela782