# What is the most effective way to access cv::Mat elements in a loop?

I need to process cv::Mat elements and there is not special OpenCV function that performs my task. So I have to iterate the elements in loop. What is the more effective way of elementwise access? cv::Mat iterators, cv::Mat::at() method, maybe pointer arithmetic by hand or something else?

edit retag close merge delete

Sort by » oldest newest most voted

If you really care about efficiency then pointer access is the most efficient. However, I suggest you to use it only in time-critical parts of your program because readability and safety is more important in other case.

See the OpenCV tutorial on this topic for details.

more

You probably will get x10 speedup by switching order of your for loops. First loop rows, than (inner) loop columns.

more

According to the official documentations, they suggest that the most efficient way is to get the pointer to the row first, and then just use the plain C operator []. It also saves a multiplication for each iteration.

// compute sum of positive matrix elements
// (assuming that M isa double-precision matrix)
double sum=0;
for(int i = 0; i < M.rows; i++)
{
const double* Mi = M.ptr<double>(i);
for(int j = 0; j < M.cols; j++)
sum += std::max(Mi[j], 0.);
}

more

For each, is the fastest access method using parallel CPU threads

more

jayrambhia's answer is approximately right, but it doesn't account for the step (also called the stride or pitch) of the Mat. You need to multiply by img.step, rather than img.cols. Also, if you're interested in speed, you want the per-colum loop nested inside the per-row loop. Something like the following. Even this assumes RGB color model in BGR component order, so it doesn't work for gray scale.

unsigned char *input = (unsigned char*)(img.data);
for(int j = 0;j < img.rows;j++){
for(int i = 0;i < img.cols;i++){
unsigned char b = input[img.step * j + i ] ;
unsigned char g = input[img.step * j + i + 1];
unsigned char r = input[img.step * j + i + 2];
}
}


}

more

Using img.step for the stepsize did not work for me with a float-type matrix (openCV type CV_32FC1). I used img.cols instead and everything worked fine.

( 2015-04-28 01:16:49 -0500 )edit
1

you need to multiply i with the number of channels too... unsigned char r = input[img.step * j + i*img.channels() + 2 ] ; etc

( 2017-01-09 09:56:46 -0500 )edit

Important!!! The answer should be edited if possible

( 2017-02-28 15:17:50 -0500 )edit

I'd say accessing it's data pointer.

Mat img = imread("filename.jpg",CV_LOAD_IMAGE_COLOR);
unsigned char *input = (unsigned char*)(img.data);

int i,j,r,g,b;
for(int i = 0;i < img.cols;i++){
for(int j = 0;j < img.rows;j++){
b = input[img.cols * j + i ] ;
g = input[img.cols * j + i + 1];
r = input[img.cols * j + i + 2];
}
}

more

Official site

GitHub

Wiki

Documentation