我有一个初始化为double类型的矩阵。但是每当我修改类型时,它存储的值总是变为int。这很奇怪,我不知道原因。代码非常简单,工作如下:
void func(Mat &mat) {
for(int i=0; i<10; i++) {
mat.data[i] = (double)i/2;
printf("data: %f\n", (double)i/2);
printf("mat: %f\n", (double)mat.data[i]);
}
}
int main() {
Mat test(1,1,CV_64FC(10), Scalar(0));
func(test);
for(int i=0; i<10; i++) {
cout << "final value: " << (double)test.data[i] << endl;
}
return 0;
}
数据可以是0.5,1.5,2.5等。但是当我从test中获取值时,它只有0,1,2和3.我不知道为什么即使我使用CV_64F它也不能存储double值。 同样很奇怪的是,在主要功能中,测试垫没有改变其值。我已通过引用传递参数,但为什么它不起作用?
答案 0 :(得分:1)
在OpenCV的core.hpp中,有这段代码
class CV_EXPORTS Mat
{
public:
...
//! pointer to the data
uchar* data;
...
};
这意味着无论Mat中存储的数据类型如何,数据指针始终为uchar*
。因此,以下行是错误的。
mat.data[i] = (double)i/2;
如果i = 5
,则(double)i/2 = 2.5
。对mat.data[i]
的赋值隐式地将2.5
强制转换为无符号字符,因此丢弃小数部分并实际存储2
。
你可以试试
((double*)mat.data)[i] = (double)i/2;
...
printf("mat: %f\n", ((double*)mat.data)[i]);
但这非常难看,直接访问数据指针的代码通常有难闻的气味。 一个更简洁的解决方案是
double* p = mat.ptr<double>(0);
for(int i = 0; i < 10; ++i) {
p[i] = (double) i / 2;
printf("data: %f\n", (double) i / 2);
printf("mat: %f\n", p[i]);
}
关于问题的第二部分,因为Mat本质上是一个智能指针,并且你没有在func()
中重新分配数据,所以你是否通过引用传递Mat并不重要。如果你有:
void func(Mat mat) { ...
但是,在main()中,以下行是错误的,因为它将双精度索引为字节
cout << "final value: " << (double)test.data[i] << endl;
将其更改为以下内容,您将获得正确的结果。
cout << "final value: " << ((double*)test.data)[i] << endl;
当然,还有许多其他可能的方法,包括:
cout << "final value: " << test.at<Vec<double, 10> >(0, 0)[i] << endl;