python中的openCV视频保存

Posted

技术标签:

【中文标题】python中的openCV视频保存【英文标题】:openCV video saving in python 【发布时间】:2015-06-01 18:14:04 【问题描述】:

我正在尝试保存视频,但无法正常工作。 我按照 openCV 文档中的说明进行操作。

import numpy as np
import cv2

cap = cv2.VideoCapture(0)

fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('output.avi', fourcc, 20.0, (640,480))

while(cap.isOpened()):
    ret, frame = cap.read()
    if ret==True:
        frame = cv2.flip(frame,0)


        out.write(frame)

        cv2.imshow('frame',frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    else:
        break
cap.release()

out.release()

cv2.destroyAllWindows()

怎么了?

【问题讨论】:

它在我的电脑上运行良好。事实上,接受的答案不起作用 确保你要写入的目录存在,否则会静默失败。 在我的系统上,只有“DIVX”有效,而 opencv 文档示例中给出的编码,即“M”、“J”、“P”、“G”,只是默默地不写入文件.我希望有一种方法可以验证编解码器,以便我的代码在编解码器可用性方面更安全地移植。 【参考方案1】:

试试这个。它对我有用(Windows 10)。

import numpy as np
import cv2

cap = cv2.VideoCapture(0)

# Define the codec and create VideoWriter object
#fourcc = cv2.cv.CV_FOURCC(*'DIVX')
#out = cv2.VideoWriter('output.avi',fourcc, 20.0, (640,480))
out = cv2.VideoWriter('output.avi', -1, 20.0, (640,480))

while(cap.isOpened()):
    ret, frame = cap.read()
    if ret==True:
        frame = cv2.flip(frame,0)

        # write the flipped frame
        out.write(frame)

        cv2.imshow('frame',frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    else:
        break

# Release everything if job is finished
cap.release()
out.release()
cv2.destroyAllWindows()

【讨论】:

这对我不起作用。仅创建一个空视频文件(大小为 5.6 kB)。 无法生成视频的请更改fourcc参数 它没有创建 output.avi 文件 问题中的代码 sn-p 工作得很好 确实问题中的代码 sn-p 工作正常,但这个答案没有。它依赖于操作系统吗?我在 ubuntu 上。【参考方案2】:

就我而言,我发现 Writer 的大小必须与相机或文件的帧大小相匹配。这样我就先阅读了帧大小,然后将其应用于写入器设置,如下所示。

(grabbed, frame) = camera.read()
fshape = frame.shape
fheight = fshape[0]
fwidth = fshape[1]
print fwidth , fheight
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('output.avi',fourcc, 20.0, (fwidth,fheight))

【讨论】:

相机未定义,相机是什么? @nycynik 如果您直接使用相机而不是保存的视频 这是唯一对我有用的解决方案。要么 OpenCV 发生了变化,要么其他人似乎都有 640x480 的网络摄像头。【参考方案3】:

https://github.com/ContinuumIO/anaconda-issues/issues/223 的 jveitchmichaelis 提供了详尽的答案。在这里我复制了他的答案:

OpenCV 中的文档说(隐藏)你只能写 使用 OpenCV3 转至 avi。不管这是不是真的,我无法做到 确定,但我无法写入其他任何内容。

然而,OpenCV 主要是一个计算机视觉库,而不是视频流、编解码器和编写器。因此,开发商试图保持 这部分尽可能简单。由于这个用于视频的 OpenCV 容器仅支持 avi 扩展,它的第一个版本。

发件人:http://docs.opencv.org/3.1.0/d7/d9e/tutorial_video_write.html

我的设置:我使用 MSVC 2015 从源代码构建了 OpenCV 3,包括 ffmpeg。我还从以下位置下载并安装了 XVID 和 openh264 Cisco,我添加到我的 PATH 中。我正在运行 Anaconda Python 3。我也 下载了最新版本的 ffmpeg 并将 bin 文件夹添加到我的 路径,尽管这不应该有所作为,因为它已经融入 OpenCV。

我在 Win 10 64 位中运行。

这段代码似乎在我的电脑上运行良好。它将生成一个视频 包含随机静态:

writer = cv2.VideoWriter("output.avi",
cv2.VideoWriter_fourcc(*"MJPG"), 30,(640,480))

for frame in range(1000):
    writer.write(np.random.randint(0, 255, (480,640,3)).astype('uint8'))

writer.release()

我通过反复试验学到的一些东西:

只能使用“.avi”,它只是一个容器,编解码器很重要。

在指定帧大小时要小心。在构造函数中,您需要将帧大小作为 (column, row) 传递,例如640x480。然而 您传入的数组被索引为(行,列)。见上文 例如它是如何切换的?

如果您的输入图像与 VideoWriter 的大小不同,它将失败(通常是静默)

仅传入 8 位图像,如果必须手动转换数组 (.astype('uint8')) 事实上,没关系,只是总是投射。即使您使用 cv2.imread 加载图像,您也需要转换为 uint8... 如果您不传入 3 通道、8 位图像,MJPG 将失败。至少我得到了一个断言失败。 XVID 还需要 3 通道图像,但如果您不这样做,则会静默失败。 H264 似乎适合单通道图像 如果您需要原始输出,例如机器视觉相机,您可以使用“DIB”。 'RAW' 或空编解码器有时会起作用。奇怪的是,如果我使用 DIB,我收到一个 ffmpeg 错误,但视频保存得很好。如果我使用RAW, 没有错误,但 Windows 视频播放器不会打开它。全部是 在 VLC 中很好。

最后,我认为关键是 OpenCV 并非旨在 一个视频捕捉库——它甚至不支持声音。视频作家 很有用,但 99% 的情况下你最好把所有的钱都存起来 图像放入文件夹并使用 ffmpeg 将它们变成有用的 视频。

【讨论】:

"(column, row) e.g. 640x480. 但是你传入的数组被索引为 (row, column)" 我因此失去了 1 天的工作。谢谢!【参考方案4】:

您需要像这样获取捕获的确切大小:

import cv2

cap = cv2.VideoCapture(0)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH) + 0.5)
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT) + 0.5)
size = (width, height)
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('your_video.avi', fourcc, 20.0, size)

while(True):
    _, frame = cap.read()
    cv2.imshow('Recording...', frame)
    out.write(frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
out.release()
cv2.destroyAllWindows()

【讨论】:

谢谢它对我有用!但你能告诉我为什么我们需要“精确”尺寸吗? @Mayan 原始视频帧宽度和高度意义上的精确尺寸。 这在窗口 10,python 3.7 上对我有用 + 0.5有什么意义?【参考方案5】:

请确保设置正确的宽度和高度。你可以像下面这样设置它

cv2.VideoWriter('output.avi', fourcc, 20.0, (int(cap.get(3)), int(cap.get(4))))

【讨论】:

【参考方案6】:

我也遇到了同样的问题,但是当我使用 'MJPG' 而不是 'XVID'

时它起作用了

我用过

fourcc = cv2.VideoWriter_fourcc(*'MJPG')

而不是

fourcc = cv2.VideoWriter_fourcc(*'XVID')

【讨论】:

【参考方案7】:

这是一个仅在 MacOS 中测试过的答案,但它可能也适用于 Linux 和 Windows。

import numpy as np
import cv2

cap = cv2.VideoCapture(0)

# Get the Default resolutions
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))

# Define the codec and filename.
out = cv2.VideoWriter('output.avi',cv2.VideoWriter_fourcc('M','J','P','G'), 10, (frame_width,frame_height))

while(cap.isOpened()):
    ret, frame = cap.read()
    if ret==True:

        # write the  frame
        out.write(frame)

        cv2.imshow('frame',frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    else:
        break

# Release everything if job is finished
cap.release()
out.release()
cv2.destroyAllWindows()

【讨论】:

这确实有效,但我的输入视频文件为 83MB,但我最终得到了 接近 1GB 大小的 output.avi您能否解释一下为什么会发生这种情况以及如何解决这个问题? 另外,为什么我需要使用相同的heightwidth【参考方案8】:

我遇到了同样的问题,然后我尝试了这个:

frame = cv2.flip(frame,180) 

而不是

frame= cv2.flip(frame,0) 

它正在工作。

【讨论】:

如果您不想翻转图像,只需删除该行,它不是必需的。【参考方案9】:

我没有像上面的答案那样遇到编解码器问题或尺寸问题。相反,我的问题是因为我的输出帧是灰度的。

我必须使用参数 isColor=False 创建一个 VideoWriter

out = cv2.VideoWriter(output_path,
                      cv2.VideoWriter_fourcc(*'mp4v'),
                      30,
                      (INPUT_VIDEO_WIDTH,INPUT_VIDEO_HEIGHT),
                      isColor=False
                      )

在API Docs 中,它错误地表示该标志目前仅在 Windows 上受支持。我在 Ubuntu 20.04 上进行了测试,使用 opencv-python==4.2.0.34,它最终正确写入文件。

【讨论】:

【参考方案10】:

这个答案涵盖了变量的含义,重要的是,输入帧和视频大小的输出大小应相同。

import cv2

save_name = "output.mp4"
fps = 10
width = 600
height = 480
output_size = (width, height)
out = cv2.VideoWriter(save_name,cv2.VideoWriter_fourcc('M','J','P','G'), fps , output_size )

cap = cv2.VideoCapture(0) # 0 for webcam or you can put in videopath
while(True):
    _, frame = cap.read()
    cv2.imshow('Video Frame', frame)
    out.write(cv2.resize(frame, output_size ))
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cap.release()
out.release()
cv2.destroyAllWindows()

【讨论】:

【参考方案11】:

Nuru 答案确实有效,唯一的事情是在if ret==True: 循环下删除这一行frame = cv2.flip(frame,0),它将输出视频文件而不翻转

【讨论】:

【参考方案12】:

举个例子:

fourcc = cv2.VideoWriter_fourcc(*'MJPG')
out_corner = cv2.VideoWriter('img_corner_1.avi',fourcc, 20.0, (640, 480))

在那个地方,必须将 X,Y 定义为宽度和高度

但是,当您创建图像(例如空白图像)时,您必须将 Y,X 定义为高度和宽度:

    img_corner = np.zeros((480, 640, 3), np.uint8)

【讨论】:

【参考方案13】:

正如@ปรีดา ตั้งนภากร所说:Writer的大小必须与相机或文件的框架相匹配。

您可以使用此类代码检查您的相机是否为(640、480):

print(int(cap.get(3)), int(cap.get(4)))

对于我自己,我发现我的相机是 (1280, 720) 并用 (1280, 720) 替换 (640, 480)。然后它可以保存视频。

【讨论】:

你想参考谁?对我来说,它表示您将 @ปรีดา ตั้งนภากร 归功于此线程中的任何人。 ปรีดา ตั้งนภากร 是回答这个问题的人之一。您可以在此线程/页面中找到/搜索他。或许还是找官方解释比较好。 啊无视,你是对的。出于某种原因,我根本没有看到他的答案。 对于好奇的人,那些波浪形的东西(泰语)发音为“Prida Tangnaphakorn”! :P【参考方案14】:
import cv2

cap = cv2.VideoCapture(0)

fourcc = cv2.VideoWriter_fourcc('X','V','I','D')
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))

out = cv2.VideoWriter('output.mp4', fourcc, 20,(frame_width,frame_height),True )
print(int(cap.get(3)))
print(int(cap.get(4)))
while(cap.isOpened()):
    ret,frame = cap.read()
    if ret == True:
        print(frame.shape)
        out.write(frame)
        cv2.imshow('Frame', frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    else:
        break
cap.release()
out.release()`enter code here`

cv2.destroyAllWindows()

这可以正常工作,但视频尺寸相对较小的问题意味着没有捕获任何内容。因此,请确保视频的高度和宽度与您要录制的图像相同。如果您在捕获视频后使用某些操作,则必须确认大小(之前和之后)。 希望它能节省一些时间

【讨论】:

【参考方案15】:

我想写一个灰度图像,但没有任何效果,我必须在 VideoWriter 中添加一个 0

out = cv2.VideoWriter(outfilename, fourcc, fps, (width, height), 0)

【讨论】:

【参考方案16】:

我有点晚了,但是VidGear Python 库的WriteGear API 使用Hardware Encoders support 和 自动将 OpenCV 帧实时流水线化到任何平台上的 FFmpeg 中同时提供相同的 opencv-python 语法。这是一个基本的python示例:

# import libraries
from vidgear.gears import WriteGear
import cv2

output_params = "-vcodec":"libx264", "-crf": 0, "-preset": "fast" #define (Codec,CRF,preset) FFmpeg tweak parameters for writer

stream = cv2.VideoCapture(0) #Open live webcam video stream on first index(i.e. 0) device

writer = WriteGear(output_filename = 'Output.mp4', compression_mode = True, logging = True, **output_params) #Define writer with output filename 'Output.mp4' 

# infinite loop
while True:
    
    (grabbed, frame) = stream.read()
    # read frames

    # check if frame empty
    if not is grabbed:
        #if True break the infinite loop
        break
    

    # do something with frame here
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # write a modified frame to writer
    writer.write(gray) 
       
    # Show output window
    cv2.imshow("Output Frame", frame)

    key = cv2.waitKey(1) & 0xFF
    # check for 'q' key-press
    if key == ord("q"):
        #if 'q' key-pressed break out
        break

cv2.destroyAllWindows()
# close output window

stream.release()
# safely close video stream
writer.close()
# safely close writer

来源:https://abhitronix.github.io/vidgear/latest/gears/writegear/compression/usage/#using-compression-mode-with-opencv

您可以查看VidGear Docs 了解更多高级应用程序和功能。

【讨论】:

以上是关于python中的openCV视频保存的主要内容,如果未能解决你的问题,请参考以下文章

python+opencv打开摄像头,保存视频拍照功能的实现

python opencv videowrite不写视频

[opencv][原创]关于opencv-python的cv2保存视频不支持H264格式问题探讨

Python OpenCV 从视频保存图片

Python之OpenCV读取视频抽帧保存

OpenCV保存摄像头视频和视频文件操作实战(附Python源码)