OpenCV  4.10.0
开源计算机视觉
加载...
搜索...
无匹配项
开始使用视频

目标

  • 了解如何读取视频、显示视频和保存视频。
  • 了解如何从摄像头捕获视频并显示。
  • 您将学习这些函数:cv.VideoCapture()cv.VideoWriter()

从摄像头捕获视频

我们经常需要用摄像头捕获实时流。OpenCV 提供了一个非常简单的接口来实现此目的。让我们从摄像头中捕获一段视频(我正在使用笔记本电脑上的内置网络摄像头),将其转换为灰度视频并显示。这是一个非常简单的入门任务。

要捕获视频,您需要创建一个 VideoCapture 对象。它的参数可以是设备索引或视频文件的名称。设备索引只是指定摄像头的数字。通常,只有一个摄像头连接(就像我的情况一样)。所以我只需传递 0(或 -1)。您可以通过传递 1 等来选择第二个摄像头。之后,您可以逐帧捕获。但在最后,不要忘记释放捕获。

import numpy as np
import cv2 as cv
if not cap.isOpened()
print("Cannot open camera")
exit()
while True
# 逐帧捕获
ret, frame = cap.read()
# 如果正确读取帧,则 ret 为 True
if not ret
print("Can't receive frame (stream end?). Exiting ...")
break
# 此处进行我们对帧的操作
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
# 显示最终帧
cv.imshow('frame', gray)
if cv.waitKey(1) == ord('q')
break
# 完成所有操作后,释放捕获
cap.release()
用于从视频文件、图像序列或摄像头进行视频捕获的类。
定义 videoio.hpp:731
void imshow(const String &winname, InputArray mat)
在指定的窗口中显示图像。
int waitKey(int delay=0)
等待按下某个键。
void destroyAllWindows()
销毁所有 HighGUI 窗口。
void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0)
将一个图像从一个色彩空间转换为另一个色彩空间。

cap.read() 返回一个 bool 值(True/False)。如果帧读取正确,则它将为 True。因此,可以通过检查该返回值来判断视频是否已结束。

有时,cap 可能尚未初始化捕获。这种情况下,该代码会显示一个错误。可以使用 cap.isOpened() 方法检查它是否已初始化。如果是 True,则正常。否则,可以使用 cap.open() 打开它。

还可以使用 cap.get(propId) 方法访问该视频的一些功能,其中 propId 是 0 至 18 之间的一个数字。每个数字表示视频的一个属性(如果它适用于该视频)。此处:cv::VideoCapture::get() 可查看完整详细信息。可以使用 cap.set(propId, value) 修改其中一些值。Value 是想要的新值。

例如,可以通过 cap.get(cv.CAP_PROP_FRAME_WIDTH)cap.get(cv.CAP_PROP_FRAME_HEIGHT) 检查帧宽度和高度。默认情况下,它提供 640x480 的尺寸。但我想将它修改为 320x240。只需使用 ret = cap.set(cv.CAP_PROP_FRAME_WIDTH,320)ret = cap.set(cv.CAP_PROP_FRAME_HEIGHT,240)

注意
如果出现错误,请使用其他任何相机应用程序(例如 Linux 中的 Cheese)确保相机工作正常。

播放文件中的视频

从文件播放视频与从相机捕获视频相同,只需将相机索引更改为视频文件名即可。此外,在显示帧时,可为 cv.waitKey() 使用合适的时间。如果时间太短,视频会播放得很快,如果时间太长,视频会播放得较慢(好吧,这是以慢动作显示视频的方式)。在一般情况下,25 毫秒将是合适的。

import numpy as np
import cv2 as cv
cap = cv.VideoCapture('vtest.avi')
while cap.isOpened()
ret, frame = cap.read()
# 如果正确读取帧,则 ret 为 True
if not ret
print("Can't receive frame (stream end?). Exiting ...")
break
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
cv.imshow('frame', gray)
if cv.waitKey(1) == ord('q')
break
cap.release()
注意
确保安装了适当版本的 ffmpeg 或 gstreamer。有时,处理视频捕捉非常头疼,主要原因是安装了错误的 ffmpeg/gstreamer。

保存视频

因此,我们捕捉到一段视频并逐帧对其进行处理,我们希望保存该视频。对于图像,这很简单:只需使用 cv.imwrite()。在此,需要多做一些工作。

这次我们创建一个 VideoWriter 对象。我们应该指定输出文件名(例如:output.avi)。然后,我们应该指定 FourCC 代码(详细信息见下一段落)。然后应传递每秒帧数 (fps) 和帧大小。最后一个是 isColor 标志。如果它为 True,编码器需要彩色帧,否则使用灰度帧。

FourCC 是用于指定视频编解码器的 4 字节代码。可在 fourcc.org 中找到可用代码列表。它取决于平台。以下编解码器对我来说很好用。

  • 在 Fedora 中:DIVX、XVID、MJPG、X264、WMV1、WMV2。(XVID 更可取。MJPG 导致视频大小高。X264 提供非常小的视频
  • 在 Windows 中:DIVX(更多测试和添加)
  • 在 OSX 中:MJPG(.mp4)、DIVX(.avi)、X264(.mkv)。

FourCC 代码作为 ‘cv.VideoWriter_fourcc('M’,'J','P','G')cv.VideoWriter_fourcc(*'MJPG')` 传递,适用于 MJPG。

以下代码从摄像头中捕捉,翻转垂直方向的每一帧,然后保存视频。

import numpy as np
import cv2 as cv
# 定义编解码器并创建 VideoWriter 对象
fourcc = cv.VideoWriter_fourcc(*'XVID')
out = cv.VideoWriter('output.avi', fourcc, 20.0, (640, 480))
while cap.isOpened()
ret, frame = cap.read()
if not ret
print("Can't receive frame (stream end?). Exiting ...")
break
frame = cv.flip(frame, 0)
# 写入翻转的帧
out.write(frame)
cv.imshow('frame', frame)
if cv.waitKey(1) == ord('q')
break
# 如果作业完成,释放所有内容
cap.release()
out.release()
视频写入器类。
定义 videoio.hpp:1009
void flip(InputArray src, OutputArray dst, int flipCode)
围绕垂直轴、水平轴或同时围绕这两个轴对二维阵列进行翻转。

附加资源

练习