Reputation: 4388
So here is something that I came upon that really bothered me and made me try and figure out why does it work this way:
If have the following super simplistic, error prone code just to show an example:
std::vector<cv::Mat> newData(3,cv::Mat(height, width, cv::DataType<T>::type));
int counter = 0;
for(int b=0; b<3; b++){
for(int i=0; i<3; i++){
for(int j=0; j<3; j++){
newData[b].at<int>(i,j) = counter++;
std::cout << newData[b].at<T>(i,j) << std::endl;
}
}
}
for(int b=0; b<3; b++){
std::cout << newData[b] << std::endl;
}
Printout:
[18, 19, 20;
21, 22, 23;
24, 25, 26]
[18, 19, 20;
21, 22, 23;
24, 25, 26]
[18, 19, 20;
21, 22, 23;
24, 25, 26]
Why is the same reference being used for the different vector entries? I am forced to create the different matrices separately as opposed to creating them along with the vector itself.
Is there a way to avoid this?
Thanks
Upvotes: 4
Views: 1410
Reputation: 227370
The issue is that cv::Mat
has reference semantics, so copying cv::Mat
objects results in the copies sharing the data with the original. Thus initializing a vector in this way
std::vector<cv::Mat> newData(N, a_cv_mat);
will result in the vector containing N cv::Mat
s all sharing the same data as a_cv_mat
.
To avoid having cv::Mat
objects that refer to the same data, you can initialize the vector using a brace enclosed initializaiton list:
std::vector<cv::Mat> newData{cv::Mat(height, width, cv::DataType<T>::type),
cv::Mat(height, width, cv::DataType<T>::type),
cv::Mat(height, width, cv::DataType<T>::type)};
If you do not know the number of elements at compile time, you can emplace them into the vector one by one:
std::vector<cv::Mat> newData
newData.emplace_back(height, width, cv::DataType<T>::type);
If you don't have C++11 support, you can push each matrix into the vector:
std::vector<cv::Mat> newData
newData.push_back(cv::Mat(height, width, cv::DataType<T>::type));
Upvotes: 5