Ask Your Question
2

How to create "list<Mat>" in 3.0?

asked 2016-06-04 21:00:54 -0600

Sheng Liu gravatar image

updated 2017-10-06 17:22:35 -0600

I intend to use multithreading to capture and process the video from my webcam, so I difine a global list to store frames. In 2.4 list<Mat>framelist;is available. However, the same code cannot be compiled in 3.0. How should I create list<Mat> in 3.0? Thanks!

edit retag flag offensive close merge delete

Comments

"I intend to use multithreading"

DAS KOMPUTERMASCHINE IST NICHT FÜR DER GEFINGERPOKEN UND MITTENGRABEN!   ODERWISE IST EASY TO SCHNAPPEN DER SPRINGENWERK, BLOWENFUSEN UND POPPENCORKEN MIT SPITZENSPARKEN.
berak gravatar imageberak ( 2016-06-05 01:05:12 -0600 )edit

I'm sorry, but I cannot catch the meaning of that sentence. It seems like German.

Sheng Liu gravatar imageSheng Liu ( 2016-06-05 02:42:50 -0600 )edit
berak gravatar imageberak ( 2016-06-05 04:58:32 -0600 )edit

2 answers

Sort by » oldest newest most voted
2

answered 2017-10-06 04:22:30 -0600

pklab gravatar image

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)
edit flag offensive delete link more

Comments

The answer is correct. It does result in copying of the image data into a private Matrix used by the consumer. If this is undesirable, the producer thread could use boost::shared_ptr <mat> and store the shared pointers in a list. The one copy of the (presumable read-only) Mat data is now shared between all users of that pointer. When the last reference to the boost::shared_ptr goes out of scope in all threads, then the Mat data is automatically freed. This results in much less copying.

opalmirror gravatar imageopalmirror ( 2017-10-06 13:42:01 -0600 )edit

@opalmirror I'm not full understand your point but I think your suggestion is not applicable to the question. The point here is not cv::Mat itself but the image data pointed by cv::Mat.data. A shared_ptr <mat> do not solves the "shallow copy" issue. Finally boost lib is supposed to be optional here.

pklab gravatar imagepklab ( 2017-10-07 02:22:37 -0600 )edit

@pklab I agree my shared_ptr comment above is not useful/pertinent.

Thank you for patiently pointing out the error in my assumptions. I'm relatively new to both opencv and boost and there's lots to learn.

I'll check back, but for now let this retraction stand to keep the history complete. I'm okay with deleting my comment too if that is advisable.

opalmirror gravatar imageopalmirror ( 2017-10-09 16:09:43 -0600 )edit
1

@opalmirror there is no reason to delete your comment but I can advise to write comment or answer only when you well know the argument ;)

pklab gravatar imagepklab ( 2017-10-10 12:33:00 -0600 )edit

@pklab Very true. I shall temper my enthusiasm somewhat. :)

opalmirror gravatar imageopalmirror ( 2017-10-13 18:09:47 -0600 )edit
1

@opalmirror you are welcome .... enthusiasm is an ingredient for knowledge :)

pklab gravatar imagepklab ( 2017-10-14 02:52:00 -0600 )edit
2

answered 2016-06-05 01:05:27 -0600

berak gravatar image

updated 2016-06-05 01:09:33 -0600

it's just:

#include "opencv2/opencv.hpp"
using namespace cv;

#include <list>
using std::list;

list<Mat> frameList;
...
edit flag offensive delete link more

Comments

Thanks a lot!

Sheng Liu gravatar imageSheng Liu ( 2016-06-05 02:34:02 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2016-06-04 21:00:54 -0600

Seen: 3,761 times

Last updated: Oct 06 '17