8

I am new to OpenCV. I am trying to use iterator instead of "for" loop, which is too slow for my case. I tried some codes like this:

MatIterator_<uchar> it, end;
for( it = I.begin<uchar>(), end = I.end<uchar>(); it != end; ++it)
{
    //some codes here
}

My question here is: how can I convert a for loop like:

for ( int i = 0; i < 500; i ++ )
{
    exampleMat.at<int>(i) = srcMat>.at<int>( i +2, i + 3 )
}

into iterator mode? That is, how can I do the "i +2, i + 3" in iterator form? I only can get the corresponding value by " *it " I think, but I couldn't get its counting number. Many thanks in advance.

E_learner
  • 3,512
  • 14
  • 57
  • 88

2 Answers2

23

It's not the for loop which is slow it is the exampleMat.at<int>(i) which is doing range checking.

To efficently loop over all the pixels you can get a pointer to the data at the start of each row with .ptr()

for(int row = 0; row < img.rows; ++row) {
    uchar* p = img.ptr(row);
    for(int col = 0; col < img.cols; ++col) {
         *p++  //points to each pixel value in turn assuming a CV_8UC1 greyscale image 
    }

    or 
    for(int col = 0; col < img.cols*3; ++col) {
         *p++  //points to each pixel B,G,R value in turn assuming a CV_8UC3 color image 
    }

}   
Martin Beckett
  • 94,801
  • 28
  • 188
  • 263
  • Dear Martin Beckett and Hammer, thank you so much for your answers. I changed my code according your suggestion, then I have two more questions: one is, I used "dstMat ( cv::Range::all(), cv::Range ( i * 5 +1, i * 5 + 4 )).setTo ( *data )" to set the dstMat value, but "dstMat" is all zero outside the loop. My second problem is: this code still uses 70-80 ms for each video frame, but I have at most 30 ms. Do you have any idea? Thank you again. – E_learner Aug 16 '12 at 08:36
  • I posted a new question here: http://stackoverflow.com/questions/11989003/opencv-set-matrix-values-with-ranges – E_learner Aug 16 '12 at 14:09
  • Is there any way the ptr method automatically return the pointer of type same as the underlying data? I could do `auto p = img.ptr(row)` but how to replace the `int` in this statement? – winterlight Mar 09 '16 at 07:55
  • 1
    @winterlight - not automatically. The storage is always bytes (char) the header defines what type you are treating it as - the compiler doesn't know. – Martin Beckett Mar 10 '16 at 05:23
1

You need some kind of counting variable and you will have to declare and update it yourself. A compact way of doing this would be

int i = 0;
for( it = I.begin<uchar>(), end = I.end<uchar>(); it != end; ++it,i++)
{
//some codes here involving i+2 and i+3
}

if you are looking for super fast access however I would recommend manipulating the data pointer yourself. For a great explanation of iterating speed look at OpenCV 2 Computer Vision Application Programming Cookbook on page 51 (65 in pdf). Your code might then look something lik

cv::Mat your_matrix;
//assuming you are using uchar
uchar* data = your_matrix.data();

for(int i = 0; i < some_number; i++)
{
  //operations using *data
  data++;
}
Hammer
  • 10,109
  • 1
  • 36
  • 52