[英]Mat& vs Mat opencv 2 c++
well I'm a little confused about passing Mat to function and retrieving it so what is the difference between let's say 好吧,我对于将Mat传递给函数并进行检索感到有些困惑,所以说之间有什么区别
void GetFrame(Mat& frame)
Vs
void GetFrame(Mat frame)
Vs
Mat GetFrame()
Update: 更新:
in which version the changes to frame inside the function body will result in change in the original frame passed to function 在哪个版本中,对函数主体内部框架的更改将导致传递给函数的原始框架发生更改
With a bit of care, you can get all 3 versions to work and do the same thing, but I will try to explain the details. 稍加小心,您就可以使所有3个版本都可以工作并执行相同的操作,但是我将尝试解释其详细信息。
First, a Mat
object is really just a small header which contains metadata about the real data, (eg, number of rows and columns), and a pointer to the actual data. 首先,
Mat
对象实际上只是一个小标题,其中包含有关真实数据的元数据(例如,行和列的数量)以及指向实际数据的指针。 In most cases, the pointer is actually a smart pointer, with reference counting, and can be shared by multiple Mat
objects, and automatically deleted when the last remaining Mat
object stops pointing to it. 在大多数情况下,指针实际上是具有引用计数的智能指针,并且可以由多个
Mat
对象共享,并且在最后一个剩余的Mat
对象停止指向它时会自动删除。 ( Mat
objects can also point to data it doesn't own, ie if you have some data you got from a different library/API, and want to reuse the same memory rather than copy it.) (
Mat
对象也可以指向它不拥有的数据,即,如果您有一些数据是从其他库/ API获得的,并且想要重用相同的内存而不是复制它。)
Version 1 of your function is perhaps the simplest. 函数的版本1可能是最简单的。 The caller's
Mat
object is copied by reference , which obviously means that any modifications to the Mat
object's metadata (including the (smart) pointer) will be visible to the caller upon return. 调用者的
Mat
对象是通过引用复制的 ,这显然意味着对Mat
对象的元数据的任何修改(包括(智能)指针)在返回时对调用者都是可见的。 The underlying data will obviously reflect any modification made by the function. 基础数据显然将反映该功能所做的任何修改。
In version 2 of your function (passing in a Mat
object by value), the small header represented by Mat
is copied and passed to the function. 在函数的版本2中(按值传递
Mat
对象),将Mat
表示的小标头复制并传递给函数。 The copy is shallow: metadata and the (smart) pointer is copied, but the underlying data is shared by the caller's Mat
object and the callee's Mat
object. 副本是浅:元数据和(智能)指针被复制,但潜在的数据由呼叫者的共享
Mat
对象和被叫方的Mat
对象。 The part that you have to be careful is that if the function modifies the metadata of the copied frame
object, these changes will not be visible to the caller . 您需要注意的部分是,如果函数修改了复制的
frame
对象的元数据, 则调用者将看不到这些更改 。
So for example, if you pass an empty Mat
, you may be surprised with the result: First, the meta-data of the empty Mat
is copied. 因此,例如,如果传递一个空的
Mat
,您可能会对结果感到惊讶:首先,复制该空Mat
的元数据。 When the function calls something like frame.create(newRows, newCols, newType);
当函数调用诸如
frame.create(newRows, newCols, newType);
, the create
function will allocate a new chunk of memory since frame.rows != newRows
, frame.cols != newCols
, and frame.type() != newType
, and the (callee's copy alone of) frame
metadata is updated reflect the newly allocated data. ,由于
frame.rows != newRows
, frame.cols != newCols
和frame.type() != newType
,并且frame
元数据(仅被调用方的副本)已更新,因此create
函数将分配新的内存块新分配的数据。 When the function returns, its frame
object will hold the only reference to the smart pointer, so the data will be automatically discarded. 当函数返回时,其
frame
对象将保留对智能指针的唯一引用,因此数据将被自动丢弃。 The caller will still have just an empty header. 调用方仍将只有一个空头。
If, however, the Mat
object that is passed in to the function already has the correct dimensions and type, frame.create()
will do nothing, which means that any modification made by the callee to the underlying data will be visible to the caller. 但是,如果传递给函数的
Mat
对象已经具有正确的尺寸和类型,则frame.create()
将不执行任何操作,这意味着被调用方对基础数据进行的任何修改对调用方都是可见的。
The 3rd version is similar to the second, except that rather than making a copy of the meta-data when the function is called, the function instead allocates a Mat
however it sees fit, and the meta-data (including pointer to the underlying data) is copied back to the caller upon return. 第三个版本与第二个版本相似,除了第一个版本不是在调用函数时复制元数据,而是在认为合适的情况下分配
Mat
以及元数据(包括指向基础数据的指针) )会在返回时复制回调用方。 The underlying data survives and is accessible to the caller. 基础数据可以保留,并且调用者可以访问。
If you don't know the size and type of the data ahead of time, you cannot use pass-by-value. 如果您不提前知道数据的大小和类型,则不能使用传递值。 If you do know the size/type, you can use pass-by-value, and the pre-allocated memory will be used.
如果您知道大小/类型,则可以使用传递值,并且将使用预分配的内存。
Pass-by-reference will use the pre-allocated memory if possible, or allocate new memory, and in either case the caller will always see the new header/data. 引用传递将在可能的情况下使用预分配的内存,或者分配新的内存,在两种情况下,调用者都将始终看到新的标头/数据。
Return-by-value also will always work properly, but it does have to re-allocate new memory every call, which may be undesirable. 按值返回也将始终正常工作,但是每次调用都必须重新分配新的内存,这可能是不可取的。
"2. Pass by value version" is INCORRECT, at least for the below example which drove me nuts, but I managed to fix using .clone() “ 2.按值传递版本”是不正确的,至少对于下面的示例,这使我很生气,但是我设法使用.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);
}
//and here is the function //这是函数
void test_if_it_adds_a_rect(Mat image, Rect rect)
{
rectangle(image, rect, CV_RGB(0, 0, 255), 2);
}
//even this one //即使这个
void test_if_it_adds_a_rect(Mat image1, Rect rect1)
{
rectangle(image1, rect1, CV_RGB(0, 0, 255), 2);
}
You will notice that the returned image has changed and has a blue rect. 您会注意到返回的图像已更改并且具有蓝色矩形。 BUT to solve this you need to use image.clone() inside the function instead of image
但是要解决这个问题,您需要在函数内部使用image.clone()而不是image
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.