Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

I would bring up this question because @berak's answer would compiles but it really should be used with care.

For example in the loop below all images in the list will be same as latest grabbed image !

VideoCapture cap(0);
list<Mat> frameList;
Mat frame;
while(1)
{
    cap >> frame;           // overwrite image data in "frame"
    frameList.push(frame);  // create a new mat header in the list (shallow copy BAD!)
    ...

This is because list.push(matVar) stores a copy of matVar. In OpenCV this means that only the Mat header is copied but not the image itself (shallow copy). If you change matVar later you also will change the image in the list. In a classical grab and push loop this is very dangerous.

Simple solution is to clone the mat into the pushed Mat

VideoCapture cap(0);
list<Mat> frameList;
Mat frame;
while(1)
{
    cap >> frame;
    Mat tmp;                        // create new empty mat
    frameList.push(tmp);            // create a new mat header in the list
    frame.copyTo(frameList.back()); // create a new mat data
    ...

More advanced solution is to create a Mat container with deep copy and create a list of your container

class MyMat
{
public:
    Mat m_mat;

    // default constructor
    MyMat() {}

    // copy constructor overload (USED BY Push)
    MyMat(const MyMat& src) {
        src.copyTo(m_mat);
    }

    // Assignment (=) Operator overloading (USED BY Pop)
    MyMat& operator=(const MyMat&src) {
        src.copyTo(m_mat);
        return *this;
    }
}

Use can use it

MyMat A,B;
A = B ; // deep copy with =operator overload
MyMat C(A); // deep copy with copy constructor overload
// grab loop
list<MyMat> myDataList;
while(1)
{
    cap >> A;
    myDataList.push(A);    // deep copy with copy constructor overload
    ...
}
// pop & show
B = myDataList.pop();   // deep copy with =operator overload
imshow("Test",B.m_mat);
// assigment
Mat m1;
m1 = B.m_mat; // m1 is pointing to B.m_mat (shallow copy)