I am trying to build a playback loop option for an OpenCV video. My program uses Python multiprocessing, and has a button send loopswitch
calls through queue4
to enable or disable the loop option. My specific problem is that my video freezes on the last frame, and I would like to know if the line vidFile.set(cv2.cv.CV_CAP_PROP_POS_FRAMES, 1)
is a correct use of the cv2.VideoCapture.set()
method, and should indeed take the video back to frame 1 and replay it (as I think it should).
After revising my code, it now triggers a runtime C++ error, but no other precisions are given.
According to this answer, it would seem that using cv2.VideoCapture.set()
to jump between frame is buggy. Has anyone managed it anyway?
Thank you,
My code for the capture process (queue
and queue2
are in and out queues):
def image_capture(queue, con, queue2, queue4):
videopath = con.recv()
vidFile = cv2.VideoCapture(videopath)
fps = vidFile.get(cv2.cv.CV_CAP_PROP_FPS)
waitframe = 1/fps
con.send(waitframe)#sending waitkey duration through pipe to update_image()
loopswitch = False #init for playing video in a loop
while True:
if queue4.empty():
pass
else:
queueval = queue4.get()
if queueval=='loop':
if loopswitch==False:
loopswitch = True
elif loopswitch==True:
loopswitch = False
try:
flag, frame=vidFile.read()
if flag==0:
if loopswitch==False:
queue2.put(None)
break
elif loopswitch==True:
vidFile.set(cv2.cv.CV_CAP_PROP_POS_FRAMES, 1)
continue
else:
queue2.put(frame)
cv2.waitKey(waitframe)
except:
continue
cv2. VideoCapture – Creates a video capture object, which would help stream or display the video.
Basically, ret is a boolean regarding whether or not there was a return at all, at the frame is each frame that is returned. If there is no frame, you wont get an error, you will get None. gray = cv2. cvtColor(frame, cv2. COLOR_BGR2GRAY)
I can get looped video playback by using an if statement for when the frame count reaches cap.get(cv2.CAP_PROP_FRAME_COUNT)
and then resetting the frame count and cap.set(cv2.CAP_PROP_POS_FRAMES, num)
to the same value. The below example keeps looping the video for me.
import cv2
cap = cv2.VideoCapture('path/to/video')
frame_counter = 0
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
frame_counter += 1
#If the last frame is reached, reset the capture and the frame_counter
if frame_counter == cap.get(cv2.CAP_PROP_FRAME_COUNT):
frame_counter = 0 #Or whatever as long as it is the same as next line
cap.set(cv2.CAP_PROP_POS_FRAMES, 0)
# Our operations on the frame come here
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Display the resulting frame
cv2.imshow('frame',gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
It also works to recapture the video instead of resetting the frame count:
if frame_counter == cap.get(cv2.CAP_PROP_FRAME_COUNT):
frame_counter = 0
cap = cv2.VideoCapture(video_name)
So at least it works for me to use cap.set(cv2.CAP_PROP_POS_FRAMES, num)
to loop a video. What happens if you reset to the zeroth frame instead of the first (like with the avi method)?
I partially solved it by replacing vidFile.set (cv2.cv.CV_CAP_PROP_POS_FRAMES, 1)
by vidFile.set(cv2.cv.CV_CAP_PROP_POS_AVI_RATIO, 0)
, although this works for .avi files only.
For python3, opencv3.1.0, raspberry pi 3
import numpy as np
import cv2
cap = cv2.VideoCapture('intro.mp4')
while(cap.isOpened()):
ret, frame = cap.read()
#cv2.namedWindow("window", cv2.WND_PROP_FULLSCREEN)
#cv2.setWindowProperty("window",cv2.WND_PROP_FULLSCREEN,cv2.WINDOW_FULLSCREEN)
if ret:
cv2.imshow("Image", frame)
else:
print('no video')
cap.set(cv2.CAP_PROP_POS_FRAMES, 0)
continue
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
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