简单传递矩阵即。 cv :: Mat到OpenCV2.4中的函数

时间:2012-06-13 14:18:47

标签: c++ opencv image-processing

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

继承人我想做的事,

  1. 在主函数中初始化cv:Mat,例如,值为0到50。
  2. 将此矩阵作为参数传递给函数foo(),而函数{{1}}依次打印出矩阵中每个元素的值。多数民众赞成。
  3. 现在我已经在多个地方读过,当这些矩阵被传递时,它只是传递的头,而不是实际的数据。那我怎么能够在被调用函数中读出这个矩阵的值,好像整个矩阵都被传递了一样?

1 个答案:

答案 0 :(得分:34)

要了解发生了什么,您需要查看 C++ constructors ,更具体地说, copy constructor

当您从另一个cv::Mat创建cv::Mat时,如:

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

调用cv::Mat复制构造函数(它是一个函数)来执行对象的副本。在我谈论复制过程中发生的事情之前,您必须意识到,当cv::Mat用于存储图像时,较大的图像可能占用内存中的数百兆字节。那么cv::Mat复制构造函数在上面的例子中做的是将a的整个标题(高度,宽度,深度信息等)复制到b ,但它不是复制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); pass the parameter by value 。这意味着它会尝试将orig的内容复制到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为~100MB,则调用copyTo()使真正的副本将占用另一个~100MB的内存,这意味着在单个函数调用中,您的程序从100MB变为200MB 。在设计系统时请记住这一点。祝你好运。