std::vector不会为多个向量条目创建cv::Mat的新引用——初始化矩阵时,数据会被覆盖



所以我遇到了一件让我很困扰的事情,让我试着弄清楚为什么它会这样工作:

如果有以下超简单、易出错的代码,只举一个例子:

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;
}

打印输出:

[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]

为什么不同的矢量条目使用相同的引用我被迫单独创建不同的矩阵,而不是将它们与向量本身一起创建。

有办法避免这种情况吗?

感谢

问题是cv::Mat具有引用语义,因此复制cv::Mat对象会导致副本与原始对象共享数据。因此以这种方式初始化矢量

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

将导致包含N个CCD_ 3的向量都共享与CCD_ 4相同的数据。

为了避免cv::Mat对象引用相同的数据,可以使用大括号括起来的初始化列表来初始化向量:

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)};

如果你在编译时不知道元素的数量,你可以把它们一个接一个地放置到向量中:

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

如果你没有C++11支持,你可以把每个矩阵推到向量中:

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

最新更新