Writing frames appended in a list onto a video in OpenCV

The code below reads a video and stores it frame by frame into a list. The reason for doing this is because I may want to have individual frames from the video for other purposes such as blurring or converting into a binary image. I then want to convert these processed frames into a video. My understanding of OpenCV lead me to write the code below but this is giving me a Expected Ptr<cv::UMat> for argument 'src' error. Why is this the case?

import cv2
vidcap = cv2.VideoCapture("ThisVid.wmv")

#store every frame from video file 
success,image = vidcap.read()
count = 0
success = True
frames = []
while success:
    frames.append(image)
    success,image = vidcap.read()
    count += 1

vidcap.release()

newframes = [] 

for i in range(0,len(frames),100):
    newframes.append(frames[i])
    
writer = cv2.VideoWriter("outputvideo.mp4",cv2.VideoWriter_fourcc(*"MP4V"),30,(512,512))
writer.write(cv2.resize(newframes,(512,512))) #write frame into output vid
writer.release()

Answer

I would like to give a suggestion:

success = True
frames = []
while success:

Instead of writing like above, write like:

frames = []
while vidcap.isOpened():

The above code make sense. If the video is opened then process its’ frames.

My second suggestion is:

frames.append(image)
success,image = vidcap.read()
count += 1

First check if the frame is returned, then append to the list.

while vid_cap.isOpened():
    success, image = vid_cap.read()
    if success:
        frames.append(image)
        count += 1

You initialized VideWriter as:

writer = cv2.VideoWriter("outputvideo.mp4", cv2.VideoWriter_fourcc(*"MP4V"), 30, (512, 512))

There are two constraints:


1- Each frame must be (512, 512) size

2- And each frame must be rgb.

If you want to have grey-scale video, you need to set isColor variable to False

writer = cv2.VideoWriter("outputvideo.mp4", cv2.VideoWriter_fourcc(*"MP4V"), 30, (512, 512), isColor=False)

Since you want each frame size (512, 512) you could do: img = cv2.resize(image, (512, 512))

while vid_cap.isOpened():
    success, image = vid_cap.read()
    if success:
        img = cv2.resize(image, (512, 512))
        frames.append(img)
        count += 1
    else:
        break

Now, Expected Ptr<cv::UMat> for argument 'src' means writer.write first argument image should be a frame, but you gave a list input. Therefore:

1- Initialize the VideoWriter object

2- Instead of “MP4V” use “mp4v” otherwise you might get a warning

2- write frames using a for-loop

writer = cv2.VideoWriter("outputvideo.mp4", cv2.VideoWriter_fourcc(*"mp4v"), 30, (512, 512))

for i in range(0, len(frames), 100):
    newframes.append(frames[i])
    writer.write(frames[i])

writer.release()

Code:


import cv2

vid_cap = cv2.VideoCapture("result.mp4")

# store every frame from video file
success, image = vid_cap.read()
count = 0
frames = []

while vid_cap.isOpened():
    success, image = vid_cap.read()
    if success:
        img = cv2.resize(image, (512, 512))
        frames.append(img)
        count += 1
    else:
        break

vid_cap.release()

newframes = []

writer = cv2.VideoWriter("outputvideo.mp4", cv2.VideoWriter_fourcc(*"mp4v"), 30, (512, 512))

for i in range(0, len(frames), 100):
    newframes.append(frames[i])
    writer.write(frames[i])  # write frame into output vid

writer.release()