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?
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.
cv2. VideoCapture – Creates a video capture object, which would help stream or display the video. cv2. VideoWriter – Saves the output video to a directory.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With