[英]Unexpected result when resizing Vector of Vector of OpenCV Mat
我使用的是Ubuntu 16.04,GCC 5.4和最新的OpenCV。 假设我有一个double的向量
std::vector<std::vector<double>> vecvecdouble;
vecvecdouble.resize(3, std::vector<double>(3, 0));
for (int j = 0; j < 3; j++){
for (int i = 0; i < 3; i++){
if (i == 0){
vecvecdouble[i][j] = 1;
vecvecdouble[i][j] = 1;
}
if (i == 1){
vecvecdouble[i][j] = 2;
vecvecdouble[i][j] = 2;
}
if (i == 1 && j == 0){
std::cout << vecvecdouble[i - 1][j] << std::endl;
std::cout << vecvecdouble[i][j] << std::endl;
std::cout << vecvecdouble[i + 1][j] << std::endl;
}
}
}
它打印
1
2
0
如预期的那样。 但是,如果我用OpenCV cv::mat
做同样的事情
std::vector<std::vector<cv::Mat>> vecvecmat;
vecvecmat.resize(
3, std::vector<cv::Mat>(3, cv::Mat(4, 4, CV_64FC1, cv::Scalar(0.0))));
for (int j = 0; j < 3; j++){
for (int i = 0; i < 3; i++){
if (i == 0){
vecvecmat[i][j].at<double>(0, 0) = 1;
vecvecmat[i][j].at<double>(0, 1) = 1;
}
if (i == 1){
vecvecmat[i][j].at<double>(0, 0) = 2;
vecvecmat[i][j].at<double>(0, 1) = 2;
}
if (i == 1 && j == 0){
std::cout << vecvecmat[i - 1][j] << std::endl;
std::cout << vecvecmat[i][j] << std::endl;
std::cout << vecvecmat[i + 1][j] << std::endl;
}
}
}
它打印
[2, 2, 0, 0;
0, 0, 0, 0;
0, 0, 0, 0;
0, 0, 0, 0]
[2, 2, 0, 0;
0, 0, 0, 0;
0, 0, 0, 0;
0, 0, 0, 0]
[2, 2, 0, 0;
0, 0, 0, 0;
0, 0, 0, 0;
0, 0, 0, 0]
这完全是意外的,因为我希望它能打印
[1, 1, 0, 0;
0, 0, 0, 0;
0, 0, 0, 0;
0, 0, 0, 0]
[2, 2, 0, 0;
0, 0, 0, 0;
0, 0, 0, 0;
0, 0, 0, 0]
[0, 0, 0, 0;
0, 0, 0, 0;
0, 0, 0, 0;
0, 0, 0, 0]
但是,如果我不尝试在一行中调整向量的大小并经过两个for循环,则实际上会返回预期的结果
std::vector<std::vector<cv::Mat>> vecvecmat;
vecvecmat.resize(3);
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3; j++){
cv::Mat mymat = cv::Mat(4, 4, CV_64FC1, cv::Scalar(0.0));
vecvecmat[i].push_back(mymat);
}
}
for (int j = 0; j < 3; j++){
for (int i = 0; i < 3; i++){
if (i == 0){
vecvecmat[i][j].at<double>(0, 0) = 1;
vecvecmat[i][j].at<double>(0, 1) = 1;
}
if (i == 1){
vecvecmat[i][j].at<double>(0, 0) = 2;
vecvecmat[i][j].at<double>(0, 1) = 2;
}
if (i == 1 && j == 0){
std::cout << vecvecmat[i - 1][j] << std::endl;
std::cout << vecvecmat[i][j] << std::endl;
std::cout << vecvecmat[i + 1][j] << std::endl;
}
}
}
这条线怎么了?
vecvecmat.resize(3, std::vector<cv::Mat>(3, cv::Mat(4, 4, CV_64FC1, cv::Scalar(0.0))));
cv::Mat
的副本构造函数的文档说 (强调我的意思):
参量
m
整体(或部分)分配给构造矩阵的数组。 这些构造函数不会复制任何数据。 相反,指向m数据或其子数组的标头被构造并与之关联。 参考计数器(如果有)增加。 因此, 当您修改使用此类构造函数形成的矩阵时,还将修改m
的相应元素 。 如果要具有子数组的独立副本,请使用Mat::clone()
。
使用此复制构造函数*将您对std::vector::resize
调用中构造的初始矩阵复制到向量的每个元素中,因此它们都指向同一数据。 修改一个矩阵时,将全部修改。
*或也许带有operator=
,它做同样的事情(我不确定是哪一个,但是它不会影响结果)
我建议像这样初始化向量:
std::vector<std::vector<cv::Mat>> vecvecmat;
vecvecmat.resize(3, std::vector<cv::Mat>());
for(auto& v : vecvecmat)
{
for(std::size_t i = 0; i < 3; ++i)
{
v.emplace_back(4, 4, CV_64FC1, cv::Scalar(0.0));
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.