1
votes

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

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. - Miki
Vec3b v is not simple types... I must use image.data - Jarek Banaś
You must.... Is homework or what? - Miki
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. - Jarek Banaś

2 Answers

1
votes

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;
    }
}
1
votes

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