问题
I'm trying to grab specific frames (e.g. frame 0, 10, 20, ...) within a video and save them as images using Python and CV2. For some reasons, my code only saves the first frame. All other frames are created, but with size 0 (they are corrupt).
How can I fix the problem?
import cv2
from numpy import integer
number = 10;
filename = "18s.mp4";
def uniform():
cap = cv2.VideoCapture(filename);
frame_count= int(cap.get(cv2.CAP_PROP_FRAME_COUNT));
print(frame_count)
for x in range(0, number):
frame_no = 1*(x/number)
frame_no_int=int(frame_no*frame_count)
cap.set(2,frame_no);
ret, frame = cap.read()
cv2.imwrite(filename+'_frame_'+str(frame_no_int)+'.jpg', frame);
# When everything done, release the capture
cap.release()
if __name__ == '__main__':
uniform()
回答1:
Apparently, CAP_PROP_POS_AVI_RATIO
(constant 2, which you were using in cap.set()
) doesn't work well. Take a look at the output of your modified script:
import cv2
from numpy import integer
number = 10
filename = 'chaplin.mp4'
def uniform():
cap = cv2.VideoCapture(filename)
frame_count= int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
print(frame_count)
for x in range(0, number):
frame_pos_ratio = 1.0*x/number
frame_no_int=int(frame_pos_ratio*frame_count)
cap.set(cv2.CAP_PROP_POS_FRAMES, frame_no_int)
print (frame_no_int, cap.get(cv2.CAP_PROP_POS_AVI_RATIO))
ret, frame = cap.read()
cv2.imwrite('_frame_'+str(frame_no_int)+'.jpg', frame)
# Attempt to go the end of film
cap.set(cv2.CAP_PROP_POS_AVI_RATIO, 1)
print (cap.get(cv2.CAP_PROP_POS_FRAMES))
# When everything done, release the capture
cap.release()
if __name__ == '__main__':
uniform()
Output:
172
(0, 6.510416666666667e-05)
(17, 6.510416666666667e-05)
(34, 6.510416666666667e-05)
(51, 6.510416666666667e-05)
(68, 6.510416666666667e-05)
(86, 6.510416666666667e-05)
(103, 6.510416666666667e-05)
(120, 6.510416666666667e-05)
(137, 6.510416666666667e-05)
(154, 6.510416666666667e-05)
150.0
As you can see, cap.get(cv2.CAP_PROP_POS_AVI_RATIO)
inside the cycle just returns a constant 6.51e-05
.
And even though there are 174 frames, cap.set(cv2.CAP_PROP_POS_AVI_RATIO, 1)
takes you only to frame 150, which is definitely a bug.
This behavior is in line with this question.
P.S. Interestingly, even cv2.CAP_PROP_FRAME_COUNT
doesn't work properly. Apparently, my video file contained only 150 frames, but they were numbered from 22 to 171, as evidenced by ffprobe -show_frames chaplin.mp4 | grep coded_picture_number
. So the output of CAP_PROP_FRAME_COUNT is just max(frame_no)+1.
来源:https://stackoverflow.com/questions/51642097/my-python-code-doesnt-save-video-frames-as-images