I prefer
void foo(const cv::Mat &src, cv::Mat &dst) // for cv::Mat only
or
void foo(InputArray src,OutputArray dst) //for cv::Mat, cv::Mat_, cv::Matx,std:vector
Both are fastest and clear.
In general, cv::Mat
has a powerful Automatic Memory Management that allocate/deallocates the memory automatically. This help developers to forget about memory management and many call statements are similar (for opencv mats only!!)
cv::Mat
consists of header that hold informations about the Mat and a pointer to a memory block that holds the Mat data (matrix,images,...).
2 (or more cv::Mat) can share same memory for data but each cv::Mat has its own header. Using mat1 = mat2
you will achieve this result. This operation is O(1) and is fast because only header (small) information will be copied.
Function headers:
void foo(cv::Mat src,cv::Mat dst) // create 2 additional headers each call
With above declaration you will create 2 new temporary headers each time you call foo
. Again memory data will be shared with calling function. Again is fast O(1) operation.
void foo(cv::Mat &src,cv::Mat &dst) // by ref, use same objects from calling function
With this 2nd declaration you are using param by reference as standard C++. This means that you are using same object instance from calling function. This is fastest method because you won't create new headers.
What's happens to mat1.data when you write mat1 = mat2
?
mat1.data
will be deallocated automatically when is used nowhere else .This is achieved by OpenCV using internal counter.
Below some showcases:
void foo(const cv::Mat &src, cv::Mat &dst)
{
cvtColor(src,dst,BGR2GRAY); // dst.data will be allocated here IF NEEDED
cvtColor(src,src,BGR2GRAY); // NOT ALLOWED because src is const
}
void bar(cv::Mat &dst)
{
cv::circle(dst,... // draw a circle on dst
}
main()
{
cv::Mat mat1,mat2,mat3,mat4,mat5,mat6;
cv::imread("some.jpg"); //allocate mem for mat1.data
foo(mat1,mat2); //new memory for mat2.data has been allocated
mat3 = cv::Mat(mat1.size(),mat1.type()); // allocate mem for mat3.data
foo(mat1,mat3); // existing mat3.data has been used (size fits)
mat4 = cv::Mat(10,10,mat1.type()); // allocate mem (SMALL SIZE) for mat4.data
foo(mat1,mat4); // no one using mat4.data than it has been deallocated.
// New memory has been allocated for mat4.data
mat5 = cv::Mat(10,10,mat1.type()); // allocate mem (SMALL SIZE) for mat5.data
mat6 = mat5; // mat5 and mat6 share same data
bar(mat5); // draw a circle
// mat6 contains circle too
foo(mat1,mat5); // existing data is still valid for mat6.
// New memory has been allocated for mat5
// now mat6 is different from mat5. It contains circle same as before.
} //deallocate memory for all mats
this works also if you are using some local var
void foo(const cv::Mat &src, cv::Mat &dst) // for cv::Mat only
{
cv::Mat local;
cv::cvtColor(src, local, cv::COLOR_BGR2GRAY);//new memory for ...
(more)
I have some remarks about the Mat parameters functions:
Mat in
as input parameter. You shall adopt theconst TypeAddress param
form, so useconst cv::Mat& in
. Like this you are sure that you are not modifying the values in the input parameter