Othman Benchekroun
Othman Benchekroun

Reputation: 2038

Reading data cv::Mat

I am looking for a better way to get data from a cv::Mat 32F3C , i was using this : Vec3f c1 = _image.at<Vec3f>(i,j); it works fine, but not very quick, i saw that this way is better :

Vec3f c1(_image.data[step[0]*i + step[1]*j + 0],_image.data[step[0]*i + step[1]*j + 1],_image.data[step[0]*i + step[1]*j + 2]);

it compiles but it's not correct, i also tried this :

Vec3f c1(_image.data[step*i + channels*j + 0],_image.data[step*i + channels*j + 1],_image.data[step*i + channels*j + 2]);

but same thing, it compile but gives me an other absurd result.

I must be missing a factor or something.

Thanks !

Upvotes: 1

Views: 2442

Answers (3)

bjoernz
bjoernz

Reputation: 3852

You may find this article in the OpenCV-Documentation useful. However, I would first write code that is easy to understand, and only optimize it, if it is apparent that I have to optimize exactly that portion of the source code.

The gist of the article is, that there are three methods for accessing the pixels:

  1. On-the-fly address calculation:

    const cv::Vec3f& pixel = img.at< cv::Vec3f >(y, x)
    
  2. Iterator:

    cv::MatIterator< cv::Vec3f > it=img.begin(), end=img.end();
    for ( ; it != end ; ++it ) (*it)[0] = (*it)[1]
    
  3. Pointer:

    cv::Vec3f* pixel_ptr;
    for (int y = 0; y < img.rows; ++y)
    {
        pixel_ptr = img.ptr<cv::Vec3f>(y);
        for  (int x = 0; x < img.cols; ++x)
        {
            (*pixel_ptr)[0] = (*pixel_ptr)[1]
            ++pixel_ptr;
        }
    }
    

Upvotes: 2

Bull
Bull

Reputation: 11951

Based on the efficient way

cv::Mat _image = something;

for(int y = 0; y < _image.rows; ++y)
{
    cv::Vec3f* _image_row = _image.ptr<cv::Vec3f>(y);
    for(int x = 0; x< _image.cols; ++x)
    {
        cout << _image_row[x] << " ";
    }
    cout << endl;
}

Upvotes: 1

bverhagen
bverhagen

Reputation: 99

You can surpass the at() function call and access the data of directly. Use cv::Mat::ptr (http://docs.opencv.org/modules/core/doc/basic_structures.html) to get a pointer to the first element of every row of your image. Next you can access all the elements in that row using the array[index]-operator.

Image data is most of the time continuous in memory, but not always (think about selecting region of interest in another cv::Mat). You can find an example here: OpenCV C++: how access pixel value CV_32F through uchar data pointer. The image rows are continuous, which is why you ask a pointer to the first element in each iteration and can then safely access the other elements.

Upvotes: 2

Related Questions