Ask Your Question
0

Grabbing the image skips current (or next) frame.

asked 2017-02-10 08:30:36 -0600

kieranfish gravatar image

Hey there, I've recently realised that all of my output videos are twice as fast as the original, so i made the program print out the current frame and noticed that it was increasing by 2 each time (2,4,6,8...). When I removed the "cap>>currentImage;" it printed 1,2,3,4,...

I just don't understand why this is happening. Is there a mistake in the way I'm printing the frame? Any help would be appreciated.

int main (int argc, char *argv[]) {

    /// CHANGE INPUT FILE HERE
    Mat currentImage;
    VideoCapture cap("testcut.avi");//"herman.avi"

    if (!cap.isOpened()) {
            cout << "Failed to open the input video" << endl;
            exit(5);}

    for(;;){
        cap>>currentImage;
        if (!cap.grab())
        {
            cout << "\n End of video, looping" << endl;
            cap.set(CV_CAP_PROP_POS_AVI_RATIO, 0);
        }
    waitKey(80);
    cout<<"frame number=         "<<cap.get(CV_CAP_PROP_POS_FRAMES)<<endl;

    }
    return 0;
}
edit retag flag offensive close merge delete

Comments

1

I don't understand your problem " my output videos are twice as fast as the original". When you read a video file using cap>> currentimage; there is no time constraint. Only time constraint is fps. first frame is at time 0 and next at 1/fps. Now if you want to play video imshow(currentimage0); sleep(1/fps) and imshow(currentimage1)

LBerger gravatar imageLBerger ( 2017-02-10 11:59:19 -0600 )edit

Yeah, sure sure. I had a video writer with CV_CAP_PROP_FPS or something set as the fps, but I took it out as I was trying to strip the code to see where it skipped the frame.

I've never played a video using imshow(currentimage0) though, I always use imshow(currentimage). Do you think it would make a difference if I didn't use cap>>currentimage every loop, and instead used it once before the loop and then called currentimage0 to display?

Edit: Do you think if I remove the cap>>currentImage and make a Mat currentImage= cap after the if loop, it will stop grabbing twice? That seems positive.

kieranfish gravatar imagekieranfish ( 2017-02-12 10:30:34 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
1

answered 2017-02-12 11:09:44 -0600

LBerger gravatar image

updated 2017-02-12 11:32:20 -0600

here a small program how I would play play a video :

void main(void)
{
    VideoCapture vRead;
    vRead.open("G:/Lib/opencv/samples/data/Megamind.avi");
    if (!vRead.isOpened())
    {
        cout<<"File not found";
        return ;
    }
    double xFps;
    xFps = vRead.get(CV_CAP_PROP_FPS);
    cout << "FPS = " << xFps << "\n";
    double x = vRead.get(CV_CAP_PROP_FRAME_COUNT);
    cout << "# frame = " << x << "\n";
    int fourcc = vRead.get(CV_CAP_PROP_FOURCC);
    string fourcc_str = format("%c%c%c%c", fourcc & 255, (fourcc >> 8) & 255, (fourcc >> 16) & 255, (fourcc >> 24) & 255);
    cout<<"Fourcc "<< fourcc_str<<endl;
    cout<<"Time to play : "<< x/xFps<<" s\n";
    TickMeter t;
    t.start();
    bool test=true;
    Mat frame;
    // FIRST METHOD too fast read frame and don't care of time
    while (test)
    {
        vRead>> frame;
        if (frame.empty())
            test=false;
        else
            imshow("video",frame);
        waitKey(1);
    }
    t.stop();
    cout<<"Play video in "<<t.getTimeMilli()<<" ms\n";
    vRead.set(CV_CAP_PROP_POS_FRAMES,0);
    test = true;
    int nbFrame=0;
    t.reset();
     // SECOND METHODtake care of timing  but too slow because vRead an imshow timing is neglected
    t.start();
    while (test)
    {
        vRead >> frame;

        if (frame.empty())
            test = false;
        else
        {
            nbFrame++;
            vRead >> frame;
            if (frame.empty())
                      test = false;                
            else
                imshow("video", frame);
             nbFrame++;
             waitKey(2000/xFps);
        }
    }
    t.stop();
    cout << "Play video in " << t.getTimeMilli() << " ms\n";
edit flag offensive delete link more

Comments

1

Perfect! The problem was in the "if (!cap.grab())" loop, as that method caused a second grab. If I use the frame.empty instead, it works out great!

Thanks a bunch.

kieranfish gravatar imagekieranfish ( 2017-02-13 01:19:29 -0600 )edit

the proposed code is too fast for me

Farshadhn gravatar imageFarshadhn ( 2017-02-19 02:58:55 -0600 )edit

@Farshadhn If you post your code, it will be easier to help. Is the issue with the video playing to fast when you imshow it or when you save it? For the imshow, make sure that the waitKey at the end is 1000/fps and that there isn't any grab inside the if(frame.empty()) loop.

kieranfish gravatar imagekieranfish ( 2017-02-20 04:52:25 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2017-02-10 08:30:36 -0600

Seen: 1,021 times

Last updated: Feb 12 '17