9

Briefly, I would like to know if it is possible to directly access pixel value of a CV_32F Mat, through Mat member "uchar* data".

I can do it with no problem if Mat is CV_8U, for example:

// a matrix 5 columns and 6 rows, values in [0,255], all elements initialised at 12
cv:Mat A;
A.create(5,6, CV_8UC1);
A = cv::Scalar(12);

//here I successfully access to pixel [4,5]
uchar *p = A.data;
int value = (uchar) p[4*A.step + 5];

The problem is when I try to do the same operation with the following matrix,

// a matrix 5 columns, 6 rows, values in [0.0, 1.0], all elements initialised at 1.2
cv::Mat B;
B.create(5,6, CV_32FC1);
B = cv::Scalar(1.2);

//this clearly does not work, no syntax error but erroneous value reported!
uchar *p = B.data;  
float value = (float) p[4*B.step + 5];

//this works, but it is not what I want to do!
float value = B.at<float>(4,5);

Thanks a lot, Valerio

valerio_sperati
  • 793
  • 2
  • 9
  • 23

2 Answers2

20

You can use ptr method which returns pointer to matrix row:

for (int y = 0; y < mat.rows; ++y)
{
    float* row_ptr = mat.ptr<float>(y);
    for (int x = 0; x < mat.cols; ++x)
    {
        float val = row_ptr[x];
    }
}

You can also cast data pointer to float and use elem_step instead of step if matrix is continous:

float* ptr = (float*) mat.data;
size_t elem_step = mat.step / sizeof(float);
float val = ptr[i * elem_step + j];
vinograd47
  • 6,320
  • 28
  • 30
5

Note that CV_32F means the elements are float instead of uchar. The "F" here means "float". And the "U" in CV_8U stands for unsigned integer. Maybe that's why your code doesn't give the right value. By declaring p as uchar*, p[4*B.step+5] makes p move to the fifth row and advance sizeof(uchar)*5, which tend to be wrong. You can try

float value = (float) p[4*B.step + 5*B.elemSize()]

but I'm not sure if it will work. Here are some ways to pass the data of [i, j] to value:

  1. value = B.at<float>(i, j)
  2. value = B.ptr<float>(i)[j]
  3. value = ((float*)B.data)[i*B.step+j]

The 3rd way is not recommended though, since it's easy to overflow. Besides, a 6x5 matrix should be created by B.create(6, 5, CV_32FC1), I think?

Manas
  • 598
  • 3
  • 14