Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading every nth frame from VideoCapture in OpenCV

Is it possible to read frames from a video in steps (eg I want to read every fifth frame of a video stream). Currently I'm doing this as a workaround but it's not very effecient.

bool bSuccess int FramesSkipped = 5;  for (int a = 0;  < FramesSkipped; a++)       bSuccess = cap.read(NextFrameBGR); 

Any suggestions so I do not have to loop through the five frames to get the desired frame?

like image 634
user3079474 Avatar asked Mar 28 '14 05:03

user3079474


People also ask

What does VideoCapture read return?

The VideoCapture class returns a video capture object which we can use to display the video. The class has several methods, for example, there is the get() method which takes a property identifier from cv2. VideoCaptureProperties and returns the value for the specified VideoCapture property.

What does cv2 VideoCapture read do?

cv2. VideoCapture – Creates a video capture object, which would help stream or display the video. cv2. VideoWriter – Saves the output video to a directory.


2 Answers

I'm afraid there's not much you can do and it's not just a shortcoming of OpenCV. You see, modern video codecs, are, generally, complex beasts. To get a higher compression rate the encoding of a frame is often dependent on previous and sometimes even successive frames.

So, most of the time you have to decode frames before the desired one even if you don't need them.

There are rather non-trivial tricks to specifically encode a video file, so that it would be cheap to get every Nth frame, but it's not feasible in general case.

That said, you can try the seeking functionality OpenCV provides (see OpenCV Seek Function/Rewind). It may (as well as may not) work faster depending on the circumstances. However, personally, I wouldn't bet on it.

like image 70
Sergei Nosov Avatar answered Oct 16 '22 17:10

Sergei Nosov


I've had success in Python 3 using a simple counter and setting the capture to that counter's frame, as follows:

import cv2  cap = cv2.VideoCapture('XYZ.avi') # For streams: #   cap = cv2.VideoCapture('rtsp://url.to.stream/media.amqp') # Or e.g. most common ID for webcams: #   cap = cv2.VideoCapture(0) count = 0  while cap.isOpened():     ret, frame = cap.read()      if ret:         cv2.imwrite('frame{:d}.jpg'.format(count), frame)         count += 30 # i.e. at 30 fps, this advances one second         cap.set(cv2.CAP_PROP_POS_FRAMES, count)     else:         cap.release()         break 

I've tried to find a way to make this a little more pythonic using a with statement but I don't believe the CV2 library has been updated for it.

like image 34
benJephunneh Avatar answered Oct 16 '22 18:10

benJephunneh