OpenCV 4.12.0
开源计算机视觉
加载中...
搜索中...
无匹配项
视频入门

目标

  • 学习如何读取视频、显示视频和保存视频。
  • 学习如何从摄像头捕获视频并显示它。
  • 你将学习以下函数:cv.VideoCapture(), cv.VideoWriter()

从摄像头捕获视频

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

要捕获视频,你需要创建一个 VideoCapture 对象。 它的参数可以是设备索引或视频文件的名称。 设备索引只是用于指定哪个摄像头的数字。 通常会连接一个摄像头(就像我的情况一样)。 所以我简单地传递 0(或 -1)。 你可以通过传递 1 来选择第二个摄像头,依此类推。 之后,你可以逐帧捕获。 但最后,别忘了释放捕获。

import numpy as np
import cv2 as cv
if not cap.isOpened()
print("无法打开摄像头")
exit()
while True:
# 逐帧捕获
ret, frame = cap.read()
# 如果帧被正确读取,ret 为 True
if not ret:
print("无法接收帧(流结束?)。 退出...")
break
# 在帧上的操作放在这里
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
# 显示结果帧
cv.imshow('frame', gray)
if cv.waitKey(1) == ord('q'):
break
# 完成所有操作后,释放捕获
cap.release()
用于从视频文件、图像序列或摄像头捕获视频的类。
Definition videoio.hpp:772
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, AlgorithmHint hint=cv::ALGO_HINT_DEFAULT)
将图像从一个颜色空间转换为另一个颜色空间。

cap.read() 返回一个布尔值(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("无法接收帧(流结束?)。 退出...")
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("无法接收帧(流结束?)。 退出...")
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:1071
void flip(InputArray src, OutputArray dst, int flipCode)
沿垂直、水平或两个轴翻转 2D 数组。