我是opencv的新手,我对编码中最简单的操作之一有疑问:将值传递给函数。
这是我想做的,
cv:Mat
用 0 到 50 的值在主函数中初始化 a 。- 将此矩阵作为参数传递给函数
foo()
,该函数又简单地打印出矩阵中每个元素的值。就是这样。
现在我在多个地方读到,当这些矩阵被传递时,只有标题被传递,而不是实际数据。那么我如何仍然能够在被调用函数中读出这个矩阵的值,就好像整个矩阵都被传递了一样?
我是opencv的新手,我对编码中最简单的操作之一有疑问:将值传递给函数。
这是我想做的,
cv:Mat
用 0 到 50 的值在主函数中初始化 a 。foo()
,该函数又简单地打印出矩阵中每个元素的值。就是这样。现在我在多个地方读到,当这些矩阵被传递时,只有标题被传递,而不是实际数据。那么我如何仍然能够在被调用函数中读出这个矩阵的值,就好像整个矩阵都被传递了一样?
要了解发生了什么,您需要查看C++ 构造函数,更具体地说是复制构造函数。
cv::Mat
当您从另一个创建 a时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);
将按值传递参数。这意味着它将尝试复制orig
into的内容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。在设计系统时请记住这一点。祝你好运。