0

I have a video and I want to obtain specific parts of that video using frame numbers and save them.

For example, if there is a video and it has total 200 frames and I want to extract some specific parts of video say from frame 15 to 30, 50 to 79, etc. and I want to save each of these parts separately.

cap= cv2.VideoCapture('Trademill.mp4')
video_length = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) 
print ("Number of frames: ", video_length)

success,image = cap.read()
count = 0
while success:
cv2.imwrite("frame%d.jpg" % count, image)          
success,image = cap.read()
count += 1

How can I do this using python and OpenCV?

codexx
  • 65
  • 1
  • 7

1 Answers1

6

Here is how I would do it:

import cv2

file = "video.avi"
parts = [(15, 30), (50, 79)]

cap = cv2.VideoCapture(file)
ret, frame = cap.read()
h, w, _ = frame.shape

fourcc = cv2.VideoWriter_fourcc(*"XVID")
writers = [cv2.VideoWriter(f"part{start}-{end}.avi", fourcc, 20.0, (w, h)) for start, end in parts]

f = 0
while ret:
    f += 1
    for i, part in enumerate(parts):
        start, end = part
        if start <= f <= end:
            writers[i].write(frame)
    ret, frame = cap.read()

for writer in writers:
    writer.release()

cap.release()

Explanation:

  1. Import the cv2 module, define the name of the video file and the parts of the file you want to save into different video files:
import cv2

file = "video.avi"
parts = [(15, 30), (50, 79)]
  1. Define a video capture device to read frames from the video file and read from it once to get the shape of the frames of the video:
cap = cv2.VideoCapture(file)
ret, frame = cap.read()
h, w, _ = frame.shape
  1. Define a fourcc (four-character code), and define a list of video writers; one for every video you want to generate:
fourcc = cv2.VideoWriter_fourcc(*"XVID")
writers = [cv2.VideoWriter(f"part{start}-{end}.avi", fourcc, 20.0, (w, h)) for start, end in parts]
  1. Define a while loop, but before that, define a variable to keep track of which frame the while loop is at in the capture device:
f = 0
while ret:
    f += 1
  1. Using a for loop inside the while loop, loop through the start and end frames of the parts, using the enumerate method to allow the program to access the index of the parts each iteration is at when needed. If the variable defined before the while loop is between (inclusive) the start and end of the part, write that frame to the corresponding video writer (using the index provided by the enumerate method):
    for i, (start, end) in enumerate(parts):
        if start <= f <= end:
            writers[i].write(frame)
    ret, frame = cap.read()
  1. Finally, release all the video writers and the capture device:
for writer in writers:
    writer.release()

cap.release()
Red
  • 26,798
  • 7
  • 36
  • 58
  • I am getting an error in h, w, _ = frame.shape. When I printed the image it is giving none. Even when I am printing the width and height and of the frames I am getting 0. I have checked the path too it is correct. And the parts of the video I saved aren't playing. Please tell me how should I solve this – codexx May 04 '21 at 13:01
  • @codexx How did you input your path? Is it the full path to the video? – Red May 04 '21 at 13:03
  • I tried to input the whole path and just the name too both are not working – codexx May 04 '21 at 14:22
  • It is windows. When I print a specific frame, the frame is not displayed and it shows not responding. – codexx May 04 '21 at 15:58
  • When I replace the line `writers[i].write(frame)` with `cv2.imwrite('new_frame_'+str(frame)+'.jpg',frame)`, it does not write anything. Can you please tell me where I could be going wrong? – user42 Feb 22 '22 at 10:42
  • 1
    @user42 The thing that went wrong is that you are using the `numpy` array `frame` to be the filename of your images at `str(frame)`. Due to the length of the string, `cv2.imwrite()` failed to write the images. You can reproduce the problem like so: https://i.stack.imgur.com/Hoz7C.png Notice how the function returned `False` when the filename is too long. – Red Feb 22 '22 at 14:08