Std :: vector does not create a new cv :: Mat reference for more than one vector record - data becomes redundant when initializing matrices

So here's what I came across that really bothered me and made me try to figure out why it works like this:

If you have the following super simplifying error 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 used for different vector records? I am forced to create different matrices separately, rather than create them together with the vector itself.

Is there a way to avoid this?

thank

+3


source to share


1 answer


The problem is that it cv::Mat

has referential semantics, so copying objects cv::Mat

results in copies sharing the data with the original. So by initializing the vector this way

std::vector<cv::Mat> newData(N, a_cv_mat);

      

will cause the vector containing N cv::Mat

to share the same data as a_cv_mat

.

To avoid having objects cv::Mat

referencing the same data, you can initialize the vector using the parenthesized initialization 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 don't know the number of elements at compile time, you can put them into a vector one at a time:

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 a vector:

std::vector<cv::Mat> newData
newData.push_back(cv::Mat(height, width, cv::DataType<T>::type));

      

+4


source







All Articles