15

我是opencv的新手,我对编码中最简单的操作之一有疑问:将值传递给函数。

这是我想做的,

  1. cv:Mat用 0 到 50 的值在主函数中初始化 a 。
  2. 将此矩阵作为参数传递给函数foo(),该函数又简单地打印出矩阵中每个元素的值。就是这样。

现在我在多个地方读到,当这些矩阵被传递时,只有标题被传递,而不是实际数据。那么我如何仍然能够在被调用函数中读出这个矩阵的值,就好像整个矩阵都被传递了一样?

4

1 回答 1

33

要了解发生了什么,您需要查看C++ 构造函数,更具体地说复制构造函数

cv::Mat当您从另一个创建 a时cv::Mat,如下所示:

cv::Mat a = cv::imread("huge.png", 1);
cv::Mat b = a;

复制构造函数(它是一个函数)cv::Mat被调用来执行对象的复制。在我谈论复制过程中发生的事情之前,您必须意识到,由于cv::Mat用于存储图像,较大的图像可能会占用数百兆的内存。因此,上面示例中的复制构造函数cv::Mat所做的是将整个标头(高度、宽度、深度信息等)复制ab中,而不是复制a(可能是数百 MB)的整个数据/像素,它只是指向(使用指针)的原始数据a

换句话说,不复制整个图像数据是一种优化/性能决策

现在,考虑这个调用函数并cv::Mat作为参数传递的代码:

void do_something(cv::Mat src)
{
    // changing src pixels will be the same as changing orig pixels
}

int main()
{
    cv::Mat orig = cv::imread("huge.png", 1);
    do_something(orig);
    return 0;
}

如果您研究过如何将参数传递给函数,您就会知道调用 do_something(a);将按值传递参数。这意味着它将尝试复制originto的内容src,但是,此过程会激活复制构造函数,cv::Mat它不会像我刚刚解释的那样制作数据的硬拷贝。

解决这个问题?如果您正在编写do_something()并且只想制作 的真实副本orig,只需创建一个新的cv::Mat并调用该方法copyTo()

void do_something(cv::Mat src)
{
    cv::Mat real_copy = src.copyTo();
    // operating on the data of real_copy will not affect orig
}

但请记住,如果src调用 ~100MBcopyTo()来制作真实副本将占用另外 ~100MB 的内存,这意味着在单个函数调用中,您的程序刚刚从 100MB 变为 200MB。在设计系统时请记住这一点。祝你好运。

于 2012-06-13T16:49:20.793 回答