How to access elements by row, col in OpenCV 2.0's new "Mat" class? The documentation is linked below, but I have not been able to make any sense of it. http://opencv.willowgarage.com/documentation/cpp/basic_structures.html#mat
5 Answers
On the documentation:
http://docs.opencv.org/2.4/modules/core/doc/basic_structures.html#mat
It says:
(...) if you know the matrix element type, e.g. it is float, then you can use at<>() method
That is, you can use:
Mat M(100, 100, CV_64F);
cout << M.at<double>(0,0);
Maybe it is easier to use the Mat_
class. It is a template wrapper for Mat
.
Mat_
has the operator()
overloaded in order to access the elements.
The ideas provided above are good. For fast access (in case you would like to make a real time application) you could try the following:
//suppose you read an image from a file that is gray scale
Mat image = imread("Your path", CV_8UC1);
//...do some processing
uint8_t *myData = image.data;
int width = image.cols;
int height = image.rows;
int _stride = image.step;//in case cols != strides
for(int i = 0; i < height; i++)
{
for(int j = 0; j < width; j++)
{
uint8_t val = myData[ i * _stride + j];
//do whatever you want with your value
}
}
Pointer access is much faster than the Mat.at<> accessing. Hope it helps!
Based on what @J. Calleja said, you have two choices
Method 1 - Random access
If you want to random access the element of Mat, just simply use
Mat.at<data_Type>(row_num, col_num) = value;
Method 2 - Continuous access
If you want to continuous access, OpenCV provides Mat iterator compatible with STL iterator
and it's more C++
style
MatIterator_<double> it, end;
for( it = I.begin<double>(), end = I.end<double>(); it != end; ++it)
{
//do something here
}
or
for(int row = 0; row < mat.rows; ++row) {
float* p = mat.ptr(row); //pointer p points to the first place of each row
for(int col = 0; col < mat.cols; ++col) {
*p++; // operation here
}
}
If you have any difficulty to understand how Method 2 works, I borrow the picture from a blog post in the article Dynamic Two-dimensioned Arrays in C, which is much more intuitive and comprehensible.
See the picture below.
OCV goes out of its way to make sure you can't do this without knowing the element type, but if you want an easily codable but not-very-efficient way to read it type-agnostically, you can use something like
double val=mean(someMat(Rect(x,y,1,1)))[channel];
To do it well, you do have to know the type though. The at<> method is the safe way, but direct access to the data pointer is generally faster if you do it correctly.
For cv::Mat_<T> mat
just use mat(row, col)
Accessing elements of a matrix with specified type cv::Mat_< _Tp > is more comfortable, as you can skip the template specification. This is pointed out in the documentation as well.
code:
cv::Mat1d mat0 = cv::Mat1d::zeros(3, 4);
std::cout << "mat0:\n" << mat0 << std::endl;
std::cout << "element: " << mat0(2, 0) << std::endl;
std::cout << std::endl;
cv::Mat1d mat1 = (cv::Mat1d(3, 4) <<
1, NAN, 10.5, NAN,
NAN, -99, .5, NAN,
-70, NAN, -2, NAN);
std::cout << "mat1:\n" << mat1 << std::endl;
std::cout << "element: " << mat1(0, 2) << std::endl;
std::cout << std::endl;
cv::Mat mat2 = cv::Mat(3, 4, CV_32F, 0.0);
std::cout << "mat2:\n" << mat2 << std::endl;
std::cout << "element: " << mat2.at<float>(2, 0) << std::endl;
std::cout << std::endl;
output:
mat0:
[0, 0, 0, 0;
0, 0, 0, 0;
0, 0, 0, 0]
element: 0
mat1:
[1, nan, 10.5, nan;
nan, -99, 0.5, nan;
-70, nan, -2, nan]
element: 10.5
mat2:
[0, 0, 0, 0;
0, 0, 0, 0;
0, 0, 0, 0]
element: 0