Access elements of vector of pointers [closed]

2019-10-03 04:02发布

问题:

I have a little complicated problem. I'll try to explain what I've done. I have a big class, which has as class-members

Mat vidImg
vector<Mat*> *VideoBuffer;
unsigned int currentVideoFrame;

I also have a class method

void loadVideoInBuffer(int num)
{
    VideoBuffer.clear();
    currentVideoFrame = 0;
    vidDev.open(ListVideos.at(num).absoluteFilePath().toStdString()); // open videofile

    while(true)
    {
        if(vidDev.read(vidImg) == false) // read from file int vidImg object
            break;
        VideoBuffer.push_back(new Mat(vidImg)); // pushback into vector
    }
    ui->tbVideo->setEnabled(true);
} 

In this I am loading some objects loaded from another file into the Videobuffer vector. If I try to load it again from this vector in another class-member which I am assigning here:

void grabAndProcessFrameVideo() // reload and show loaded inage
{
    if(vidFlag == true)
    {   
        vidImg = Mat(*(VideoBuffer[currentVideoFrame]));  // load from vector
        currentVideoFrame++; // inc index for vector
        imshow("img",vidImg); // show reloaded object in another window
    }
}

The Mat Object and imshow function are from the opencv lib but I think that this doesn't really matter. My problem is, that it just shows the last image. If I try to access the buffervector directly in the loading function in this way

void EAMViewer::loadVideoInBuffer(int num)
{
    ui->tbVideo->setDisabled(true);
    VideoBuffer.clear();
    currentVideoFrame = 0;
    if(vidDev.open(ListVideos.at(num).absoluteFilePath().toStdString()) == false)
    {
        newLineInText(tr("no Device found"));
        return;
    }
    while(true)
    {
        if(vidDev.read(vidImg) == false)
            break;
        VideoBuffer.push_back(new Mat(vidImg));
        imshow("img",Mat(*(VideoBuffer)[currentVideoFrame]));
        waitKey(30);
        currentVideoFrame++;
    }
    currentVideoFrame = 0;
    ui->tbVideo->setEnabled(true);
}

Then it shows me it as wanted. So I think that the vector Pointer constellation is problematical if I stay in scope.

My questions are now: 1. Why the program don't crash while grabbing and processing? 2. and what can i do, that it prevent deleting?

Thanks in advance,

Inge

回答1:

The reason for why only the last frame is shown is that Mat is a reference-counted class. So when you do something like

Mat vidImg;
vidDev.read(vidImg);

Mat* a =  new Mat(vidImg);

a and vidImg are pointing at the same image. So all your elements in your vector are all pointing to the same (last loaded) image. What you want to do is:

Mat a = vidImg.clone(); 

or in your case (removing the pointers too since they shouldn't be there :) )

vector<Mat> VideoBuffer;
VideoBuffer.push_back(vidImg.clone());

So:

  1. Remove all pointers (shouldn't have them raw anyways), since Mat is already a "handle" type class
  2. use the clone() method to copy the image data.


回答2:

I believe it might be because you're dereferencing the vector which as you have it is a pointer to a vector and not a vector, rather than the element that it actually contains.

Maybe try changing

vector<Mat*> *VideoBuffer;

to

vector<Mat*> VideoBuffer;

I would also suggest using a vector of smart pointers rather than raw pointers because at the moment your code is leaking memory all over the place. If you stick with the raw pointers you ought to delete each element of the buffer vector before you clear it as clear alone won't deallocate the memory

You'll also need to change

imshow("img",Mat(*(VideoBuffer)[currentVideoFrame]));

to

imshow("img",Mat(*VideoBuffer[currentVideoFrame]));

in the lower while loop



回答3:

Have you got any loop that calls grabAndProcessFrameVideo() so it shows you all the images?

Could it be that it's showing all your images but really fast so you can only see the last one? If so, add a pause like you have in loadVideoInBuffer() (waitKey(30);) and you should see all the images.