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。 您能否解释一下为什么会发生这种情况以及如何解决这个问题? 另外,为什么我需要使用相同的height
和width
?【参考方案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打开摄像头,保存视频拍照功能的实现