Ask Your Question

# Fill a vector<vector<Mat>>

I want to fill a vector<vector<mat>> B with a Mat dest, this matrix will change in a for loop. The problem is B[0][0] is the same that B[last_number][last_numer]. Here is the code:

vector<vector<Mat>> B;
for (int i = 0; i<2; i++) {
B.push_back(vector<Mat>());
for (int j = 0; j < 3; j++)
B[i].push_back(Mat::zeros(10, 10, CV_64F));
}

Mat dest = Mat::ones(10, 10, CV_64F);
for (int i = 0; i<2; i++) {
for (int j = 0; j < 3; j++)
{
dest = 2 * dest;
B[i][j] = dest;
}
}

cout << B[0][0];


An this is the output:

[64, 64, 64, 64, 64, 64, 64, 64, 64, 64;
64, 64, 64, 64, 64, 64, 64, 64, 64, 64;
64, 64, 64, 64, 64, 64, 64, 64, 64, 64;
64, 64, 64, 64, 64, 64, 64, 64, 64, 64;
64, 64, 64, 64, 64, 64, 64, 64, 64, 64;
64, 64, 64, 64, 64, 64, 64, 64, 64, 64;
64, 64, 64, 64, 64, 64, 64, 64, 64, 64;
64, 64, 64, 64, 64, 64, 64, 64, 64, 64;
64, 64, 64, 64, 64, 64, 64, 64, 64, 64;
64, 64, 64, 64, 64, 64, 64, 64, 64, 64]

edit retag close merge delete

## Comments

as berak has well explained your problem is shallow copy. Here I would just suggest a different method to declare your matrix. You might avoid push_backwhich causes an automatic reallocation of the allocated storage space. When it's possible I prefer to construct a container with N x M elements like below:

int rows = 2; int cols = 3;
vector<vector <Mat>> B(rows, vector<Mat>(cols)); //rows x cols matrix of cv::Mat
Mat dest = Mat::ones(10, 10, CV_64F);
for (int r = 0; r<rows; r++)
for (int c = 0; c < cols; c++) {
dest *= 2;
dest.copyTo(B[r][c]);
}

( 2017-07-31 11:46:42 -0500 )edit

## 1 answer

Sort by ยป oldest newest most voted

yea, careful there ..

if you do something simple as Mat A,B; A=B; , then this is a shallow copy, then both Mats will point to the same data ! (another one, my favourite: vector<Mat> T(10,Mat(1,1,0)); same problem !)

here's a simplified example:

Mat A(1,1,CV_32F,1.0f);
Mat B = A;
cerr << A << " " << B << endl;
A = 3;
cerr << A << " " << B << endl;

[1] [1]
[3] [3] // yea, both.


to achieve a deep copy, use B=A.clone() or A.copyTo(B)

in your example above, you unfortunately reassign dest to itself (and then to B), so all your B's are indeed the same.

remedy:

either do a clone() (expensive):

for (int i = 0; i<2; i++) {
for (int j = 0; j < 3; j++)  {
dest = 2 * dest;
B[i][j] = dest.clone();


or avoid the situation, by creating a new Mat header (the temp result from the multiplication):

for (int i = 0; i<2; i++) {
for (int j = 0; j < 3; j++)  {
B[i][j] = dest * (1<<((i+1)*(j+1)));

more

## Comments

@berak To underline side effect of shallow copy It's never enough Tank you !

But, are you sure 2nd option is less expensive ? The point here is that new data must be allocated and assigned for each Mat in B. This is the expensive part which happens either with clone or within temp result. In addiction creating new mat header for the temp result introduces useless overhead.

For sure using clone or copyTo is much more clean and general solution.

( 2017-07-31 11:27:43 -0500 )edit
1

@pklab , i thould a) would be: per-element mult, then make a new Mat, and copy over, b) would be: make a new Mat, initialize each element. i think, it saves a copy.

but right, it should be: dest.copyTo(B[i][j]); so it can reuse an existing B Mat

( 2017-07-31 11:44:19 -0500 )edit
1

ok, user says matrix will change in a for loop maybe his dest *= 2 is just a test. What in case of dest is a video frame or something else ?

( 2017-07-31 11:57:35 -0500 )edit

Official site

GitHub

Wiki

Documentation

## Stats

Asked: 2017-07-31 05:58:28 -0500

Seen: 1,382 times

Last updated: Jul 31 '17