1

I have problem with access to data from Mat.data. I perform operations on picture and I need access to every pixel separately. I have to necessairly operate on simple types (float, int etc). The way I am accesing data is like below:

for (int idx = 0; idx < image.rows; idx++) {
        for (int idy = 0; idy < image.cols; idy++) {
            int color_tid = idx * image.cols * image.channels() + idy * image.channels();
            uint8_t blue = image.data[color_tid];
            uint8_t green = image.data[color_tid + 1];
            uint8_t red = image.data[color_tid + 2];
            float pixelVal = (int) blue + (int) green + (int) red;
            (...)
        }
    }

This approach is working correctly only to square images (NxN pixels), but for NxM there are anomalies outside the square area (smaller edge). Do anyone know any other way to acces data of the picture Mat? Example image (correct result):

enter image description here

anomalies (my problem)

enter image description here

4
  • 2
    Without seeing all your code, is hard to tell what's going on. However, inside your loop you can just write: Vec3b v = image(row, col); float pixelVal = v[0] + v[1] + v[2];. Also remember that rows are y coordinates, while cols are x. So you probably just swapped your indices in the first place. Commented Jan 11, 2016 at 2:04
  • Vec3b v is not simple types... I must use image.data Commented Jan 11, 2016 at 12:12
  • You must.... Is homework or what? Commented Jan 11, 2016 at 12:14
  • ehh, I wanted to skip context. I must use simple type because code is use in Cuda. I send to device array image.data because I can't use Mat function. Commented Jan 11, 2016 at 13:27

2 Answers 2

1

I recommend to follow the data layout in a Mat

enter image description here

so your loop becomes:

for (int r = 0; r < img.rows; ++r)
{
    for (int c = 0; c < img.cols; ++c)
    {
        uchar* ptr  = img.data + img.step[0] * r + img.step[1] * c;
        uchar blue  = ptr[0];
        uchar green = ptr[1];
        uchar red   = ptr[2];

        float pixelVal = blue + green + red;
    }
}

You can eventually perform a little less operations like:

for (int r = 0; r < img.rows; ++r)
{
    uchar* pt = img.data + img.step[0] * r;
    for (int c = 0; c < img.cols; ++c)
    {
        uchar* ptr  = pt + img.step[1] * c;
        uchar blue  = ptr[0];
        uchar green = ptr[1];
        uchar red   = ptr[2];

        float pixelVal = blue + green + red;
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Thx for response, but your method generates same problem like my. Tomorrow i will examine it in details, and will write if it is exact the same problem
@jak5z this works ok, and also handles non continuous matrices. But your approach works ok on continuous matrices, so I bet that the problem is about how you pass the data. Again, without an minimal reproducible example, is hard to tell.
I not using this metod but I know is fine. Thx
1

The code in your question contains a few flaws:

  • rows and columns are swapped (row is Y, column is X)
  • step size between rows (aka "stride") does not always equal to the number of columns

Using Mat::at<> makes the code much simpler:

 for(int row = 0; row < image.rows; ++row)
 {
     for(int col = 0; col < image.cols; ++col)
     {
         const Vec3b& pt = image.at<Vec3b>(row, col);
         float pixelVal = pt[0] + pt[1] + pt[2];
         ...    
     }   
 } 

2 Comments

const Vec3b& pt = image.at<Vec3b>(row, col); is not simple types... I must use image.data
@jak5z: Miki 's solution should work for you, as well. I am surprised it did not.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.