Sunday 15 November 2015

Difference between copyTo,clone and assignment operator in OpenCV

Since  we have to deal with image of larger sizes, loading the images over and over again would decrease the computational efficiency of the program.
Thus we make use of the concept called image headers.

The basic idea is that each Mat object would have their unique headers but the matrix can be shared between the two instance by having the matrix pointers point to the same memory location.
Thus copy operator would only copy header but not the actual matrix data,thus saving the computational time.

Mat A, C;                                 // creates just the header parts
A = imread(argv[1], CV_LOAD_IMAGE_COLOR); // here we'll know the method used (allocate matrix)

Mat B(A);                                 // Use the copy constructor

C = A;                                    // Assignment operator

The interesting part here is that  Mat objects B and C just copy the Matrix headers and not the actual matrix data.Thus changing any of the matrix would reflect the change on the other.

// OpenCV copy constructor and assignment operator 
#include <opencv2/core/core.hpp> 
#include <opencv2/highgui/highgui.hpp> 
#include <iostream>

using namespace cv;
using namespace std;

int main()
{
 Mat B,A;
 A = Mat::ones(2, 5, CV_8UC1);
 B = A;
 Mat C(A);
 cout<<"MAT A: \n"<<A<<"\n \n";
 cout<<"MAT B: \n"<<B<<"\n \n";
 cout<<"MAT C: \n"<<C<<"\n \n";
 return 0;
}
Output:
MAT A:
[1, 1, 1, 1, 1;
1, 1, 1, 1, 1]

MAT B:
[1, 1, 1, 1, 1;
 1, 1, 1, 1, 1]

MAT C:
[1, 1, 1, 1, 1;
1, 1, 1, 1, 1]


See the output of the below code:
// OpenCV copy constructor and assignment operator  
#include <opencv2/core/core.hpp> 
#include <opencv2/highgui/highgui.hpp> 
#include <iostream>

using namespace cv;
using namespace std;

int main()
{
 Mat B,A;
 A = Mat::ones(2, 5, CV_8UC1);
 B = A;
 Mat C(A);
 B=B*5;
 cout<<"MAT A: \n"<<A<<"\n \n";
 cout<<"MAT B: \n"<<B<<"\n \n";
 cout<<"MAT C: \n"<<C<<"\n \n";
 return 0;
}
Output:
MAT A:
[5, 5, 5, 5, 5;
 5, 5, 5, 5, 5]

MAT B:
[5, 5, 5, 5, 5;
 5, 5, 5, 5, 5]

MAT C:
[5, 5, 5, 5, 5;
 5, 5, 5, 5, 5]
Note:Matrix A and C also gets changed due to change in Matrix B.

copyTo and clone:

Mat A = B.clone();
Mat C;
B.copyTo(C);

Here by changing the matrix data of Mat objects B and C wont reflect the change to that on the other matrix.For e.g if we are changing the matrix values of A then B and C would no longer be affected by that of the corresponding change in A because the copyTo and clone operator copies the actual data of the matrix not just its headers
To copy the underlying matrix of an image we use copyTo and clone operator.

Analyse the output of the below code:

// OpenCV copyTO,clone Tutorial 
#include <opencv2/core/core.hpp> 
#include <opencv2/highgui/highgui.hpp> 
#include <iostream>

using namespace cv;
using namespace std;

int main()
{
Mat A = Mat::ones(2, 5, CV_8UC1);
Mat B=A.clone();
Mat C;
A.copyTo(C);
 cout<<"MAT A: \n"<<A<<"\n \n";
 cout<<"MAT B: \n"<<B<<"\n \n";
 cout<<"MAT C: \n"<<C<<"\n \n";
 return 0;
}

Output:
MAT A:
[1, 1, 1, 1, 1;
 1, 1, 1, 1, 1]

MAT B:
[1, 1, 1, 1, 1;
 1, 1, 1, 1, 1]

MAT C:
[1, 1, 1, 1, 1;
 1, 1, 1, 1, 1]

// OpenCV copyTO,clone Tutorial 
#include <opencv2/core/core.hpp> 
#include <opencv2/highgui/highgui.hpp> 
#include <iostream>

using namespace cv;
using namespace std;

int main()
{
Mat A = Mat::ones(2, 5, CV_8UC1);
Mat G = Mat::eye(2, 5, CV_8UC1);
Mat B=A.clone();
B=B*5;
Mat C;
G.copyTo(C);
G=G*6;
 cout<<"MAT A: \n"<<A<<"\n \n";
 cout<<"MAT B: \n"<<B<<"\n \n";
 cout<<"MAT C: \n"<<C<<"\n \n";
 cout<<"MAT G: \n"<<G<<"\n \n";
 return 0;
}

Output:
MAT A:
[1, 1, 1, 1, 1;
 1, 1, 1, 1, 1]

MAT B:
[5, 5, 5, 5, 5;
 5, 5, 5, 5, 5]

MAT C:
[1, 0, 0, 0, 0;
 0, 1, 0, 0, 0]

MAT G:
[6, 0, 0, 0, 0;
 0, 6, 0, 0, 0]

Difference between clone() and copyTo():
Analyse the output of the two codes.

copyTo:
// OpenCV copyTo Tutorial 
#include <opencv2/core/core.hpp> 
#include <opencv2/highgui/highgui.hpp> 
#include <iostream>

using namespace cv;
using namespace std;

int main()
{
Mat A = Mat::ones(2, 5, CV_8UC1);
cout<<"MAT A before clone opeation: \n"<<A<<"\n \n";
Mat B = A;
Mat C = Mat::eye(2, 5, CV_8UC1);
A=C.clone();
 cout<<"MAT A: \n"<<A<<"\n \n";
 cout<<"MAT B: \n"<<B<<"\n \n";
 cout<<"MAT C: \n"<<C<<"\n \n";
 return 0;
}

Output:
MAT A before clone opeation:
[1, 1, 1, 1, 1;
 1, 1, 1, 1, 1]

MAT A:
[1, 0, 0, 0, 0;
 0, 1, 0, 0, 0]

MAT B:
[1, 1, 1, 1, 1;
 1, 1, 1, 1, 1]

MAT C:
[1, 0, 0, 0, 0;
 0, 1, 0, 0, 0]

clone():
// OpenCV clone Tutorial 
#include <opencv2/core/core.hpp> 
#include <opencv2/highgui/highgui.hpp> 
#include <iostream>

using namespace cv;
using namespace std;

int main()
{
Mat A = Mat::ones(2, 5, CV_8UC1);
cout<<"MAT A before copyTo operation: \n"<<A<<"\n \n";
Mat B = A;
Mat C = Mat::eye(2, 5, CV_8UC1);
C.copyTo(A);
 cout<<"MAT A: \n"<<A<<"\n \n";
 cout<<"MAT B: \n"<<B<<"\n \n";
 cout<<"MAT C: \n"<<C<<"\n \n";
 return 0;
}
Output:
MAT A before copyTo operation:
[1, 1, 1, 1, 1;
 1, 1, 1, 1, 1]

MAT A:
[1, 0, 0, 0, 0;
 0, 1, 0, 0, 0]

MAT B:
[1, 0, 0, 0, 0;
 0, 1, 0, 0, 0]

MAT C:
[1, 0, 0, 0, 0;
 0, 1, 0, 0, 0]

Thus by comparing the output of copyTo() and clone() we see that when the destination matrix and the source matrix have the same type and size, copyTo will not change the address of the destination matrix, while clone will always allocate a new address for the destination matrix.

No comments:

Post a Comment