Ask Your Question
1

How can I get one single frame from a video file?

asked 2013-01-07 02:20:42 -0600

denorb gravatar image

I would like to use Python and the OpenCV wrapper to display a video that is just being recorded to the hard drive in a Python program. To achieve this I have to get the last single frame from the video that is just being written to. Is there a way to get only the last frame (or any other single frame for that matter) from the video file without loading all the frames into memory first? The video is saved as single frame bitmaps, so decoding should not be a problem.

Alternatively I could also use Python and OpenCV itself for recording the video, however I need to be able to set a fixed recording frame rate and I could not find any way to achieve that with OpenCV.

Thanks for your help!

edit retag flag offensive close merge delete

2 answers

Sort by » oldest newest most voted
1

answered 2014-07-10 03:31:40 -0600

Stéfane gravatar image

updated 2014-07-30 05:52:57 -0600

Well, I don't believe there's a seek. You need to do it. For example I do it like this :

#include "opencv2/opencv.hpp"
#include "iostream"

using namespace cv;
using namespace std;
int main(int, char**)
{
    VideoCapture cap ( "tree.avi" ); // open the default camera
    if( ! cap.isOpened () )  // check if we succeeded
        return -1;

    /* Mat edges; */
    namedWindow ( "tree" , 1 );
    double frnb ( cap.get ( CV_CAP_PROP_FRAME_COUNT ) );
    std::cout << "frame count = " << frnb << endl;

    for(;;) {
      Mat frame;
      double fIdx;

      std::cout << "frame index ? ";
      std::cin >> fIdx;
      if ( fIdx < 0 || fIdx >= frnb ) break;
      cap.set ( CV_CAP_PROP_POS_FRAMES , fIdx );
      bool success = cap.read(frame); 
      if ( ! success ) {
    cout << "Cannot read  frame " << endl;
    break;
      }
      /* cap >> frame; // get a new frame from camera */
      imshow("tree", frame);
      if ( waitKey (0) == 27 ) break;
    }
    // the camera will be deinitialized automatically in VideoCapture destructor
    return 0;
}

But, there's some errors I can't explain. The execution is OK 'till you start it with an index at most 100 though the FRAME_COUNT says 451 !? For example, let's tell the first frame to read is #100, next you can read any frame indexed before or after 100. I'd like to fix it. I also try the Haris' code but I met the same bug, i.e. the last frame (#450) isn't read... If you could help me to understand I'll be grateful....

Well, there's no pb ! The test video file was corrupted !!! Thus, you can use the code without trouble.

edit flag offensive delete link more
3

answered 2013-01-07 06:22:58 -0600

Haris gravatar image

updated 2014-01-07 23:44:23 -0600

Hi, You can refer OpenCV documentation about Reading and Writing Images and Video

  • Get total frame count using VideoCapture::get by passing the id CV_CAP_PROP_FRAME_COUNT.

  • Then using VideoCapture::set set the index to next frame to be captured, note that the index is 0 based.

See below code

 VideoCapture cap("video1.mp4"); 
    if( !cap.isOpened()){
         cout << "Cannot open the video file" << endl;
         return -1;
    }

    double count = cap.get(CV_CAP_PROP_FRAME_COUNT); //get the frame count
    cap.set(CV_CAP_PROP_POS_FRAMES,count-1); //Set index to last frame
    namedWindow("MyVideo",CV_WINDOW_AUTOSIZE);

    while(1)
    {
        Mat frame;
        bool success = cap.read(frame); 
        if (!success){
          cout << "Cannot read  frame " << endl;
          break;
        }
        imshow("MyVideo", frame);
        if(waitKey(0) == 27) break;
    }
edit flag offensive delete link more

Comments

1

so there's no seek? you need to go through the whole file?

Jared gravatar imageJared ( 2014-01-07 13:34:07 -0600 )edit
1

@Jared Hi thanks for noticing me that, I have edited my answer.

Haris gravatar imageHaris ( 2014-01-07 23:38:06 -0600 )edit

Question Tools

Stats

Asked: 2013-01-07 02:20:42 -0600

Seen: 63,907 times

Last updated: Jul 30 '14