The problem about the global variable of vector<cv::Mat> and temporary cv::Mat variable

asked 2015-05-26 00:29:39 -0600

我干过豪哥 gravatar image

updated 2015-05-26 00:31:58 -0600

 #include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>


using namespace std;
using namespace cv;


cv::Mat Right(Size(768,576),CV_8UC3);
cv::Mat Left(Size(768,576),CV_8UC3);

vector<Mat> mapx;
vector<Mat> mapy;


cv::VideoCapture capture1("test.avi");


void MapInit(const Mat &src)
{
    Mat map_x(src.size(),CV_32FC1);
    Mat map_y(src.size(),CV_32FC1);
    for( int i = 0; i < src.rows; ++i)
    {
        for( int j = 0; j < src.cols; ++j)
        {
            map_x.at<float>(i, j) = j ;
            map_y.at<float>(i, j) = src.rows - i ;
        }
    }
    mapx.push_back(map_x);
    mapy.push_back(map_y);
    //Mat map_x1(src.size(),CV_32FC1);
    //Mat map_y1(src.size(),CV_32FC1);
    for( int i = 0; i < src.rows; ++i)
    {
        for( int j = 0; j < src.cols; ++j)
        {
            map_x.at<float>(i, j) = src.cols - j ;
            map_y.at<float>(i, j) =  i ;
            //map_x1.at<float>(i, j) = src.cols - j ;
            //map_y1.at<float>(i, j) =  i ;
        }
    }
    //mapx.push_back(map_x1);
    //mapx.push_back(map_y1);
    mapx.push_back(map_x);
    mapy.push_back(map_y);
}

void mapPlane(const Mat &src)
{
    remap(src,Left,mapx[0],mapy[0],0);
    flip(Left,Left,0);
    remap(src,Right,mapx[1],mapy[1],0);
    //mapx[0] is the same as mapx[1];mapy[0] is the same as mapy[1] ???
    flip(Right,Right,0);
}
void runCam()
{
    namedWindow("test1",0);
    namedWindow("test2",0);
    for(;;)
    {   
        cv::Mat image;
        capture1 >> image;

        if(image.empty())
            exit(0) ;
        cvtColor(image,image,CV_BGR2RGB);
        if(mapx.empty() && mapy.empty())
            MapInit(image);
        mapPlane(image);
        imshow("test1",Left);
        imshow("test2",Right);
        waitKey(20);
    }
}

int main(int argc, char **argv)
{
    if(!capture1.isOpened())
    {
        printf("open failed \n");
        return -1;
    }
    runCam();
    return 0;
}

As above, I create the temporary variable Mat map_x map_y in Function MapInit(),to my surprise, when I pushback the different map_x map_y into vector<mat> mapx,mapy in order,the element of vector<mat> are the same as the latest modified map_x map_y. Similarly, I write a section of code as following,the elements in the vector result are different,which is contradicted against the above example. I am so confused about that.

#include <iostream>
#include <vector>
using namespace std;

vector<int> result;

void fun()
{
    int i = 0;
    result.push_back(i);
    i = 1;
    result.push_back(i);
}
int main()
{
    fun();
    cout<<result[0]<<endl;
    cout<<result[1]<<endl;
}
edit retag flag offensive close merge delete

Comments

So you are saying that all the element in vector<mat> contains the same element copied multiple times? IMHO it is correct if you do it like that. The Mat object is not stored into the vector, but its reference is, so when you change the Mat object, the values at the address of the object are changed, so when calling mapx[i], you are reading from the address of map_x that has just changed. On the contrary if you do something like mapx.push_back(map_x.clone()), or mapx.push_back(cv::Map(map_x)), you'll get the result you want.

thdrksdfthmn gravatar imagethdrksdfthmn ( 2015-05-26 02:39:16 -0600 )edit

If you read this, you'll understand: "Use a copy constructor or assignment operator where there can be an array or expression on the right side (see below). As noted in the introduction, the array assignment is an O(1) operation because it only copies the header and increases the reference counter. The Mat::clone() method can be used to get a full (deep) copy of the array when you need it."

thdrksdfthmn gravatar imagethdrksdfthmn ( 2015-05-26 02:41:49 -0600 )edit