简单地说,我想知道是否可以直接访问像素值 一个CV_32F Mat,通过Mat成员“uchar * data”。
如果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);
非常感谢Valerio
答案 0 :(得分:18)
您可以使用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
指针转换为float并使用elem_step
代替step
:
float* ptr = (float*) mat.data;
size_t elem_step = mat.step / sizeof(float);
float val = ptr[i * elem_step + j];
答案 1 :(得分: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 = B.at<float>(i, j)
value = B.ptr<float>(i)[j]
value = ((float*)B.data)[i*B.step+j]
不建议使用第3种方式,因为它很容易溢出。此外,我认为B.create(6, 5, CV_32FC1)
应创建一个6x5矩阵?