为什么Mat的类型变成int,即使我在OpenCV中使用double初始化它并且通过引用参数也不起作用?

时间:2014-08-14 23:30:28

标签: c++ opencv

我有一个初始化为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值。 同样很奇怪的是,在主要功能中,测试垫没有改变其值。我已通过引用传递参数,但为什么它不起作用?

1 个答案:

答案 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;