I've searched thoroughly and have not found a straightforward answer to this.
Passing opencv matrices (cv::Mat
) as arguments to a function, we're passing a smart pointer. Any change we do to the input matrix inside the function alters the matrix outside the function scope as well.
I read that by passing a matrix as a const reference, it is not altered within the function. But a simple example shows it does:
void sillyFunc(const cv::Mat& Input, cv::Mat& Output){
Output = Input;
Output += 1;
}
int main( int argc, char** argv ){
cv::Mat A = cv::Mat::ones(3,3,CV_8U);
std::cout<<"A = \n"<<A<<"\n\n";
cv::Mat B;
sillyFunc(A,B);
std::cout<<"A = \n"<<A<<"\n\n";
std::cout<<"B = \n"<<B<<"\n\n";
}
Clearly, A
is altered even though it is sent as a const cv::Mat&
.
This does not surprise me as within the function I2
is a simple copy of I1
's smart pointer and thus any change in I2
will alter I1
.
What does baffle me is that I don't understand what practical difference exists between sending cv::Mat
, const cv::Mat
, const cv::Mat&
or cv::Mat&
as arguments to a function.
I know how to override this (replacing Output = Input;
with Output = Input.clone();
would solve the problem) but still don't understand the above mentioned difference.
Thanks guys!
It's all because OpenCV uses Automatic Memory Management.
That said, in order to make two
cv::Mat
s point to different things, you need to allocate memory separately for them. For example, the following will work as expected:P.S:
cv::Mat
contains anint* refcount
that points to the reference counter. Check out Memory management and reference counting for more details:Differences between sending
cv::Mat
,const cv::Mat
,const cv::Mat&
orcv::Mat&
as arguments to a function:cv::Mat Input
: pass a copy ofInput
's header. Its header will not be changed outside of this function, but can be changed within the function. For example:const cv::Mat Input
: pass a copy ofInput
's header. Its header will not be changed outside of or within the function. For example:const cv::Mat& Input
: pass a reference ofInput
's header. Guarantees thatInput
's header will not be changed outside of or within the function. For example:cv::Mat& Input
: pass a reference ofInput
's header. Changes toInput
's header happen outside of and within the function. For example:P.S.2: I must point out that, in all the four situations (
cv::Mat
,const cv::Mat
,const cv::Mat&
orcv::Mat&
), only the access to the Mat's header is restrained, not to the data it points to. For example, you can change its data in all the four situations and its data will indeed change outside of and within the function:When you pass a smart pointer as a reference you can, theoretically, save some processing time, since smart pointer's copy-constructor is not invoked.