OpenCV 视频入门

本文主要内容来自于 OpenCV-Python 教程OpenCV 中的 GUI 功能 部分,这个部分的主要内容如下:

目标

从摄像头采集视频

通常,我们必须用摄像头捕捉实时流。OpenCV 提供了一个非常简单的接口来做这些。让我们从摄像头采集一段视频(我使用我笔记本电脑上内置的 webcam),把它转换为灰度视频并显示。只是一个入门的简单任务。

要捕捉视频,我们需要创建一个 VideoCapture 对象。它的参数可以是设备索引或视频文件的文件名。设备索引只是一个用于指定使用那个摄像头的数字。通常连接了一个摄像头(就我而言)。因而,我简单地传入 0 (或 -1)。你可以通过传入 1 选择第二个摄像头等等。随后你可以一帧一帧地捕捉图像。最后,不要忘记释放 capture。

#!/use/bin/env python
import sys

import numpy as np
import cv2 as cv


def main():
    cap = cv.VideoCapture(0)
    if not cap.isOpened():
        print("Cannot open camera")
        sys.exit()

    while True:
        # Capture frame-by-frame
        ret, frame = cap.read()

        # if frame is read correctly ret is True
        if not ret:
            print("Can't receive frame() (stream end?). Exiting ...")
            break
        # Our operations on the frame come here
        gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
        # Display the resulting frame
        cv.imshow('frame', gray)
        if cv.waitKey(1) == ord('q'):
            break

    cap.release()
    cv.destroyAllWindows()


if __name__ == "__main__":
    main()

cap.read() 返回一个布尔值 (True/False)。如果正确地读取了帧,它为 True。因此可以通过检查这个返回值来确认视频是否结束。

有时,cap 可能还没有初始化捕捉。在那种情况下,这段代码将显示错误。我们可以通过 cap.isOpened() 方法检查它是否初始化。如果它是 True,则 OK。否则使用 cap.open() 打开它。

我们还可以使用 cap.get(propId) 方法访问这个视频的一些功能,其中 propId 是一个从 0 到 68 的数字。每个数字表示视频的一个属性(如果它适用于该视频的话)。完整的描述可以在这里找到: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)。如:

    width = cap.get(cv.CAP_PROP_FRAME_WIDTH)
    height = cap.get(cv.CAP_PROP_FRAME_WIDTH)
    fps = cap.get(cv.CAP_PROP_FPS)
    print("FPS:{}, width x height: {} x {}".format(fps, width, height))

可以得到如下输出:

FPS:30.0, width x height: 640.0 x 640.0

注意:如果遇到了错误,则可以使用任何其它的摄像头应用程序(比如 Linux 下的 Cheese)来确认摄像头是否工作良好。

播放视频文件

播放视频文件与从摄像头采集类似,只是把摄像头索引改为视频文件的文件名。同样在显示视频帧的时候,传入适当的时间调用 cv.waitKey()。如果时间值太低,则视频会非常快,如果它太高,则视频会非常慢(好吧,这就是我们可以慢动作显示视频的方式)。一般情况下 25 毫秒就不错。

def play_video_file():
    cv.samples.addSamplesDataSearchPath("/media/data/my_multimedia/opencv-4.x/samples/data")
    cap = cv.VideoCapture(cv.samples.findFile("vtest.avi"))
    while cap.isOpened():
        ret, frame = cap.read()
        # if frame is read correctly ret is 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(25) == ord('q'):
            break
    cap.release()
    cv.destroyAllWindows()

cap.get(propId) 可用的 propId 由一些枚举值定义,这其中部分适用于摄像头的 VideoCapture,部分则适用于视频文件的 VideoCapture。对于视频文件,我们可以通过给 cap.get(propId) 传入 cv.CAP_PROP_FRAME_COUNT 获得视频文件的视频帧总数。

注意,请确保安装了适当版本的 ffmpeg 或 gstreamer。有时使用 video capture 比较头疼,这大多数是由于 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)。

cv.VideoWriter_fourcc('M','J','P','G')cv.VideoWriter_fourcc(*'MJPG') 的形式为 MJPG 传 FourCC
码。

如下的代码从摄像头捕捉图形,在垂直方向翻转每一帧,并保存视频。

def save_video_file():
    cap = cv.VideoCapture(0)
    # Define the codec and create VideoWriter object
    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)
        # write the flipped frame
        out.write(frame)
        cv.imshow('frame', frame)
        if cv.waitKey(1) == ord('q'):
            break
    # Release everything if job is finished
    cap.release()
    out.release()
    cv.destroyAllWindows()

Done.

参考文档 Getting Started with Videos

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值