垫&安培; vs Mat opencv 2 c ++

时间:2015-02-07 13:23:48

标签: c++ opencv

我对将Mat传递给函数并检索它有点困惑 那么让我们说

之间的区别是什么
 void GetFrame(Mat& frame)
          Vs 
 void GetFrame(Mat frame) 
          Vs 
 Mat GetFrame()

更新

在哪个版本中,对函数体内部框架的更改将导致传递给函数

的原始框架发生更改

2 个答案:

答案 0 :(得分:4)

有点小心,你可以让所有3个版本都能正常工作并做同样的事情,但我会尝试解释细节。

首先,Mat对象实际上只是一个小标题,其中包含有关实际数据的元数据(例如,行数和列数),以及指向实际数据的指针。在大多数情况下,指针实际上是一个带引用计数的智能指针,可以由多个Mat对象共享,并在最后剩余的Mat对象停止指向它时自动删除。 Mat个对象也可以指向它不拥有的数据,即如果你有一些来自不同库/ API的数据,并希望重用相同的内存而不是复制它。)< / em>的

1。通过参考版本

你的功能的第1版可能是最简单的。调用者的Mat对象通过引用复制,这显然意味着调用者可以看到对Mat对象的元数据(包括(智能)指针)的任何修改。返回。基础数据显然会反映该功能所做的任何修改。

2。按值传递

在函数的第2版中(按值传递Mat个对象),Mat表示的小标题被复制并传递给函数。副本很浅:元数据和(智能)指针被复制,但底层数据由调用者的Mat对象和被调用者的Mat对象共享。您必须小心的部分是,如果函数修改了复制的frame对象的元数据,调用者将无法看到这些更改。

例如,如果您传递空Mat,您可能会对结果感到惊讶:首先,复制空Mat的元数据。当函数调用frame.create(newRows, newCols, newType);之类的函数时,create函数将分配一个新的内存块,因为frame.rows != newRowsframe.cols != newColsframe.type() != newType以及(被调用者)单独复制frame元数据更新反映新分配的数据。当函数返回时,其frame对象将保留对智能指针的唯一引用,因此数据将被自动丢弃。调用者仍然只有一个空标题。

但是,如果传递给函数的Mat对象已经具有正确的维度和类型,则frame.create()将不执行任何操作,这意味着被调用者对基础进行的任何修改数据将对调用者可见。

3。按价值版本返回

第三个版本与第二个版本类似,不同之处在于,当调用函数时,函数不是复制元数据,而是分配Mat,但它认为合适,并且元数据(包括指向底层数据的指针)在返回时被复制回调用者。基础数据存活并且可以被调用者访问。

摘要

如果您未提前知道数据的大小和类型,则无法使用传值。如果您确实知道大小/类型,则可以使用pass-by-value,并使用预分配的内存。

传递引用将尽可能使用预先分配的内存,或者分配新的内存,在任何一种情况下,调用者都将始终看到新的头/数据。

按值返回也将始终正常工作,但它必须在每次调用时重新分配新内存,这可能是不合需要的。

答案 1 :(得分:0)

&#34; 2。通过价值版本&#34;是不正确的,至少在下面的例子中让我疯了,但我设法修复使用.clone()

Mat image = imread("anyimage.jpg");
Rect rect(Point(40, 50), Point(60,80) ); // assuming size is over 80
if(!image.empty())
{
imshow("original image",image);
waitKey(0);

test_if_it_adds_a_rect(image, rect);
imshow("returned image",image);
waitKey(0);
}

//这里是函数

void test_if_it_adds_a_rect(Mat image, Rect rect)
{
 rectangle(image, rect, CV_RGB(0, 0, 255), 2); 
}

//甚至这一个

void test_if_it_adds_a_rect(Mat image1, Rect rect1)
{
rectangle(image1, rect1, CV_RGB(0, 0, 255), 2); 
}

您会注意到返回的图像已更改并且具有蓝色矩形。 但要解决这个问题,你需要在函数内使用image.clone()而不是image