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.
VideoCapture.read() skipped frames?
`cv2.VideoCapture().grab()` skips frames with .webm videos
python - Does Cap.read() skip frames in camera stream but not when running from file? - Stack Overflow
python - How to skip missing images/frames within an image sequence when used with cv2.videocapture()? - Stack Overflow
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.
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 am working on a school project which is related to Image Processing using OpenCV Python and Raspberry Pi 3.
The hardware of Raspberry Pi 3 cannot handle the video from camera consecutively, therefore I'm thinking about only capture a picture after every 5 seconds from the camera and use it to recognize what I need, then continue.
I did some research on the internet and found a function called time.sleep(5), however this function only pause the camera 5 seconds and then continue.
Can anyone help me to solve my problem. Thank you so much. Sorry for my bad English, here is my code so far. In my code, I use a video to test first, then when figure out the solution, I will apply on camera.
import cv2
import numpy as np
import time
headcc = cv2.CascadeClassifier('lib/heads_cascade.xml')
cap = cv2.VideoCapture('image/hockey_game.avi')
def video():
ret, frame = cap.read()
# gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
head = headcc.detectMultiScale(frame, 1.2, 2, 0 , (20, 20), (40, 40))
print type(head)
print head
print head.shape
print "Number of heads detected: " + str(head.shape[0])
if len(head) > 0:
for (x, y, w, h) in head:
cv2.rectangle(frame, (x,y), (x+w, y+h), (0, 255, 255), 1)
cv2.rectangle(frame, ((0,frame.shape[0] -25)),(270, frame.shape[0]), (255,255,255), -1)
cv2.putText(frame, "Number of head detected: " + str(head.shape[0]), (0,frame.shape[0] -10), cv2.FONT_HERSHEY_TRIPLEX, 0.5, (0,0,0), 1)
cv2.namedWindow('Camera',cv2.WINDOW_NORMAL)
cv2.imshow('Camera',frame)
while(cap.isOpened()):
video()
time.sleep(5)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()Update March 15th, 2018: Thanks to comment from Joe, I have found the way to skip frames. However, the program still cannot know whether the video ends, and also the fps code still appear 0.0. So if there is any help for these errors, I will really appreciate. Here is the code so far:
import cv2
import numpy as np
import time
headcc = cv2.CascadeClassifier('lib/heads_cascade.xml')
cap = cv2.VideoCapture('image/hockey_game.avi')
fps = cap.get(cv2.CAP_PROP_POS_FRAMES)
def video():
ret, frame = cap.read()
# gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
head = headcc.detectMultiScale(frame, 1.2, 2, 0 , (20, 20), (40, 40))
# print type(head)
# print head
# print head.shape
print "Number of heads detected: " + str(head.shape[0])
if len(head) > 0:
for (x, y, w, h) in head:
cv2.rectangle(frame, (x,y), (x+w, y+h), (0, 255, 255), 1)
# cv2.rectangle(frame, ((0,frame.shape[0] -25)),(270, frame.shape[0]), (255,255,255), -1)
# cv2.putText(frame, "Number of head detected: " + str(head.shape[0]), (0,frame.shape[0] -10), cv2.FONT_HERSHEY_TRIPLEX, 0.5, (0,0,0), 1)
cv2.namedWindow('Camera',cv2.WINDOW_NORMAL)
cv2.imshow('Camera',frame)
while(cap.isOpened()):
video()
cf = cap.get(cv2.CAP_PROP_POS_FRAMES) - 1
cap.set(cv2.CAP_PROP_POS_FRAMES, cf+50)
# cv2.setTrackbarPos("pos_trackbar", "Frame Grabber",
int(cap.get(cv2.CAP_PROP_FPS)))
time.sleep(2)
if (cv2.waitKey(1) & 0xFF == ord('q')):
break
print fps
cap.release()
cv2.destroyAllWindows()I have a lot of long video samples (1-2 minutes) I've been using to test some computer vision code on, but the real-world use case would be taking in live image data over a couple seconds. Is there a way to take only a few seconds of video from the middle of one of the long videos? I can't just take frames from the start of the video since the phenomena I'm trying to analyze doesn't start till a while into the video.
I probably could brute force it by just going through the first section of frames without doing any analysis on them but I'd prefer a more elegant solution if there is one.
Edit: I should specify I'm using Python
I'm reading a frame from a usb webcam, but I need the frame to be guaranteed to be taken by the camera after I request it. Unfortunately, I get the last buffed frame. What I'm doing now is calling read twice, once to flush the buffer, and once to wait for and get another image. This works pretty well but seems to fail 2% of the time or so, and cuts my frame rate in half (under ideal circumstances it would be slower but not by that much if I'm thinking clearly). I just don't understand what it's actually doing. How do I make sure to get the next available frame that wasn't taken before I called cv.VideoCapture.read ?