Dirty Penguin
Dirty Penguin

Reputation: 4402

OpenCV - Capture arbitrary frame from video file

I use the following code to extract a specific frame from a video file. In this example, I'm simply getting the middle frame:

import cv2
video_path = '/tmp/wonderwall.mp4'
vidcap = cv2.VideoCapture(video_path)
middle_frame = int(vidcap.get(cv2.CAP_PROP_FRAME_COUNT) / 2)
success, image = vidcap.read()
count = 0
success = True
while success:
    success, image = vidcap.read()
    if count == middle_frame:
        temp_file = tempfile.NamedTemporaryFile(suffix='.jpg', delete=False)
        cv2.imwrite(temp_file.name, image)
    count += 1

However, with this method, capturing the middle frame in a very large file can take a while.

Apparently, in the older cv module, one could do:

import cv
img = cv.QueryFrame(capture)

Is there a similar way in cv2 to grab a specific frame in a video file, without having to iterate through all frames?

Upvotes: 0

Views: 2304

Answers (1)

Ebya
Ebya

Reputation: 428

You can do it in the same way, in C++ (python conversion should be more than easy).

cv::VideoCapture cap("file.avi");
double number_of_frame = cap.get(CV_CAP_PROP_FRAME_COUNT);
cap.set(CV_CAP_PROP_POS_FRAMES, IndexOfTheFrameYouWant);
cv::Mat frameIwant = cap.read();

For reference :

VideoCapture::get(int propId)

Can take various flag returning nearly all you can wish for (http://docs.opencv.org/2.4/modules/highgui/doc/reading_and_writing_images_and_video.html and look for get() ).

 VideoCapture::set(int propId, double value)

Set will do what you want (same doc look for set) if you use the propID 1, and the index of the frame you desire. You should note that if the index you use as parameter is superior to the max frame that the code will grab the last frame of the video if you are lucky, or crash at run time.

Upvotes: 2

Related Questions