9

简而言之,我想知道是否可以通过 Mat 成员“uchar* data”直接访问 CV_32F Mat 的像素值。

如果 Mat 是 CV_8U,我可以毫无问题地做到这一点,例如:

// 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];

问题是当我尝试对以下矩阵进行相同的操作时,

// 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);

非常感谢,瓦莱里奥

4

2 回答 2

20

您可以使用ptr返回指向矩阵行的指针的方法:

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

您还可以将data指针转换为浮点数并使用elem_step而不是step如果矩阵是连续的:

float* ptr = (float*) mat.data;
size_t elem_step = mat.step / sizeof(float);
float val = ptr[i * elem_step + j];
于 2013-07-10T12:46:52.250 回答
5

请注意,CV_32F 表示元素是float而不是uchar. 这里的“F”表示“浮动”。CV_8U 中的“U”代表unsigned integer. 也许这就是您的代码没有给出正确值的原因。通过将 p 声明为uchar*p[4*B.step+5]使 p 移动到第五行并提前sizeof(uchar)*5,这往往是错误的。你可以试试

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

但我不确定它是否会起作用。以下是一些将 [i, j] 的数据传递给 value 的方法:

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

但是不推荐第三种方式,因为它很容易溢出。B.create(6, 5, CV_32FC1)此外,我认为应该由 6x5 矩阵创建?

于 2013-07-10T11:30:53.870 回答