Ask Your Question
14

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

asked 2012-06-27 11:11:21 -0600

Maria Dimashova gravatar image

updated 2020-10-28 02:44:15 -0600

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 flag offensive close merge delete

6 answers

Sort by ยป oldest newest most voted
13

answered 2012-06-27 12:40:46 -0600

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.

edit flag offensive delete link more
4

answered 2014-09-24 11:11:14 -0600

lvv gravatar image

updated 2014-09-25 12:02:22 -0600

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

edit flag offensive delete link more
2

answered 2015-05-07 03:11:21 -0600

beahacker gravatar image

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.);
}
edit flag offensive delete link more
0

answered 2019-08-23 15:01:09 -0600

MoeMoe gravatar image

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

edit flag offensive delete link more
0

answered 2013-02-13 20:00:09 -0600

xaffeine gravatar image

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];
    }
}

}

edit flag offensive delete link more

Comments

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.

jshtok gravatar imagejshtok ( 2015-04-28 01:16:49 -0600 )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

BoozeAddict gravatar imageBoozeAddict ( 2017-01-09 09:56:46 -0600 )edit

Important!!! The answer should be edited if possible

Croolman gravatar imageCroolman ( 2017-02-28 15:17:50 -0600 )edit
0

answered 2012-06-27 13:52:01 -0600

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];
        }
  }
edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2012-06-27 11:11:21 -0600

Seen: 143,460 times

Last updated: Sep 25 '14