I'm writing a simple OpenCV script in python to do some machine learning. I want to feed it a sequence of video files that it will process and then exit and spit out some parameters. However when I open a video file with cv2.VideoCapture it loops infinitely. How can I detect when I hit the end of the video?
**Edit ** So a few people noted that there should be an empty frame returned when the read hits end of file. I tried looking for that and it works on my Linux machine but doesn't on my mac. On the mac it just loops and keeps going as if there is no end to the file. Any ideas?
Code is shown below for the reading loop, it loops infinitely unless I hit the esc key.
cam = cv2.VideoCapture(sourceVideo)
while True:
ret, img = cam.read()
cv2.imshow('detection', img)
print ret
if (0xFF & cv2.waitKey(5) == 27) or img.size == 0:
break
Note that ret always returns as True, and the img is always valid data. Is it possible that I shouldn't be using VideoCapture() for this kind of reading? I don't want to use the older cv commands because I need to be using the NumPy arrays that cv2 uses.
** Edit ** Ok, found a reasonable solution. I found that at least one other person has had a similar issue in Mac OS: OpenCV capture loops video/Does not detect last frame
My guess is that there is an issue either with the OpenCV setup we have in Mac OS or with the file format somehow.
The correct solution generally is to check the type of the returned frame, so this should work:
cam = cv2.VideoCapture(sourceVideo)
while True:
ret, img = cam.read()
if (type(img) == type(None)):
break
cv2.imshow('detection', img)
print ret
if (0xFF & cv2.waitKey(5) == 27) or img.size == 0:
break
However, if you're having the problem I am, the final frame doesn't get detected. At any rate, there is a reasonable workaround, which is to check the number of frames in the file and simply keep track.
framecount = cam.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT)
frames = 0
while frames < framecount:
ret, img = cam.read()
frames += 1
if (type(img) == type(None)):
break
cv2.imshow('detection', img)
print ret
if (0xFF & cv2.waitKey(5) == 27) or img.size == 0:
break