【问题标题】:Writing frames appended in a list onto a video in OpenCV将列表中附加的帧写入 OpenCV 中的视频
【发布时间】:2021-03-16 14:48:41
【问题描述】:

以下代码读取视频并将其逐帧存储到列表中。这样做的原因是因为我可能希望将视频中的单个帧用于其他目的,例如模糊或转换为二进制图像。然后我想将这些处理过的帧转换成视频。我对 OpenCV 的理解使我编写了下面的代码,但这给了我一个 Expected Ptr<cv::UMat> for argument 'src' 错误。为什么会这样?

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()

【问题讨论】:

  • 代码中的哪一行给出了该错误?

标签: python opencv frame


【解决方案1】:

cv2.resize 需要个人图像。您正在提供不符合预期签名的图像列表。此外,cv2.VideoWriter.write 一次只写入一帧,而您提供的是帧列表。因此,在您使用newframes 的循环中,甚至不要使用新列表。在循环中调整帧大小,然后写入磁盘。

writer = cv2.VideoWriter("outputvideo.mp4",cv2.VideoWriter_fourcc(*"MP4V"),30,(512,512))
for i in range(0,len(frames),100):
    resiz = cv2.resize(frames[i], (512, 512))
    writer.write(resiz)
writer.release()

【讨论】:

  • 感谢您的支持 - 我想让答案简短明了以解决 OP 的问题。尽管接受的答案有其优点,但我发现解决这个问题有点太长了。但是,如果您首先讨论代码有什么问题,然后解决它然后提供建议,则可以保持这种风格。
【解决方案2】:

我想提个建议:

success = True
frames = []
while success:

不要像上面那样写,而是写成:

frames = []
while vidcap.isOpened():

上面的代码很有意义。如果视频已打开,则处理其帧。

我的第二个建议是:

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

首先检查是否返回frame,然后追加到列表中。

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

您将VideWriter 初始化为:

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

有两个约束:


1- 每帧必须为 (512, 512) 大小

2-而且每一帧都必须是rgb。

如果你想要灰度视频,你需要将isColor变量设置为False

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

既然你想要每个帧大小(512, 512),你可以这样做: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

现在,Expected Ptr<cv::UMat> for argument 'src' 的意思是 writer.write 第一个参数 image 应该是一个框架,但您提供了一个列表输入。因此:

1- 初始化VideoWriter 对象

2- 使用“mp4v”代替“MP4V”,否则您可能会收到警告

2- 使用 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()

代码:


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()

【讨论】:

  • 感谢您的回答和一步一步的推理。我可以在我的方法中看到错误并相应地纠正它们。我也只是估计帧大小,但后来发现我可以通过img.shape 得到它们。这使得编写框架变得容易。
  • 不客气。是的,您可以使用img.shape。如果img.shape 只返回两个变量,让我给你一个提示(也许你已经知道),这意味着图像是灰度的。即(512, 512)是灰度图像,如果img.shape返回三变量即(512, 512, 3)则图像是rgb。
  • img.shape 分别返回高度和宽度。因此在使用时,获取高度和宽度:h, w = img.shape[:2] 然后将VideoWriter 初始化为writer = cv2.VideoWriter("outputvideo.mp4", cv2.VideoWriter_fourcc(*"mp4v"), 30, (w, h)) 不要忘记为灰度帧或图像设置isScale=False
猜你喜欢
  • 2012-08-25
  • 1970-01-01
  • 2017-07-07
  • 2016-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-25
相关资源
最近更新 更多