我是opencv的新手,我对编码中最简单的操作之一有疑问:将值传递给函数。
继承人我想做的事,
cv:Mat
,例如,值为0到50。foo()
,而函数{{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 。在设计系统时请记住这一点。祝你好运。