Jarek Banaś
Jarek Banaś

Reputation: 31

OpenCV Mat to array access

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

Upvotes: 1

Views: 1609

Answers (2)

Miki
Miki

Reputation: 41765

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

Upvotes: 1

alexm
alexm

Reputation: 6882

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

Upvotes: 1

Related Questions