OpenCV读取实时相机画面和视频文件

「这是我参与2022首次更文挑战的第5天,活动详情查看:2022首次更文挑战

读取相机画面和视频文件

在某些需要实时计算机视觉项目中,必须捕捉实时相机画面(例如,使用笔记本电脑的摄像头或监控摄像机捕捉画面)。在 OpenCV 中,使用 cv2.VideoCapture 作为从不同来源捕获视频的类,例如图像序列、视频文件和相机。

读取相机画面

编写 read_camera.py 用于从连接到计算机的相机读取画面。首先看下完整程序,然后再进行详细解释:

import cv2
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("index_camera", help="index of the camera to read from", type=int)
args = parser.parse_args()

capture = cv2.VideoCapture(args.index_camera)
if capture.isOpened()is False:
    print("Error opening the camera")
while capture.isOpened():
    ret, frame = capture.read()

    if ret is True:
        cv2.imshow('Input frame from the camera', frame)
        gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        cv2.imshow('Grayscale input camera', gray_frame)
        if cv2.waitKey(20) & 0xFF == ord('q'):
            break
    else:
        break
capture.release()
cv2.destroyAllWindows()

复制代码

cv2.VideoCapture 所必需的参数是 index_camera,它指示要读取的相机的索引。如果有一个摄像头连接到计算机,则它的索引为 0 ,如果有第二台摄像头,可以通过传递参数值 1 来选择它,以此类推;需要注意的是,该参数的类型是 int 。

parser = argparse.ArgumentParser()
parser.add_argument("index_camera", help="index of the camera to read from", type=int)
args = parser.parse_args()
复制代码

使用 cv2.VideoCapture 的第一步是创建一个要使用的对象 capture

capture = cv2.VideoCapture(args.index_camera)
复制代码

如果 index_camera 为 0,则相当于调用 cv2.VideoCapture(0) 。为了检查连接是否已正确建立,需要使用 capture.isOpened() 方法,如果无法建立连接,该方法返回 False;如果正确初始化,则此方法返回 True。 要从相机逐帧捕获画面,需要调用 capture.read() 方法,该方法从相机返回帧;同时还将返回一个布尔值,此布尔值指示是否已从 capture 对象正确读取帧。

while capture.isOpened():
    # 逐帧获取相机画面
    ret, frame = capture.read()
    if ret is True:
        # 显示捕获的帧画面
        cv2.imshow('Input frame from the camera', frame)
复制代码

获取的相机帧画面与 OpenCV 读取的图像具有相同的结构,因此可以像处理图像一样处理它。例如,要将帧画面转换为灰度:

		# 将从相机捕获的帧转换为灰度图像
		gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
		# 显示灰度帧图像
        cv2.imshow('Grayscale input camera', gray_frame)
复制代码

接下来,实现按下 q 键退出程序的功能,ord('q') 返回 q 字符对应的 8 位 ASCII 值,而 cv2.waitKey() 与 0xFF 的 按位与 (&) 运算用于仅获取 cv2.waitKey() 的最后 8 位。因此,可以对这两个值进行比较,如果相等则退出程序:

        # 按下 q 键可退出程序执行
        if cv2.waitKey(20) & 0xFF == ord('q'):
            break
复制代码

最后,释放所有内容 (cv2.VideoCapture,并销毁创建的窗口):

capture.release()
cv2.destroyAllWindows()
复制代码

通过在命令行中执行以下命令,运行脚本:

python read_camera.py 0
复制代码

可以看到运行结果显示了相机获取的实时画面:

获取相机画面

访问捕获画面对象的属性

可以使用 capture.get(property_identifier) 访问 capture 对象的某些属性,例如帧宽度、帧高度和每秒帧数 (Frames Per Second, FPS)。如果调用不受支持的属性,则返回值将为 0:

import cv2

capture = cv2.VideoCapture(0)

# 获取 VideoCapture 的属性 (frame width, frame height and frames per second (fps)):
frame_width = capture.get(cv2.CAP_PROP_FRAME_WIDTH)
frame_height = capture.get(cv2.CAP_PROP_FRAME_HEIGHT)
fps = capture.get(cv2.CAP_PROP_FPS)

# 打印属性值
print("CV_CAP_PROP_FRAME_WIDTH: '{}'".format(frame_width))
print("CV_CAP_PROP_FRAME_HEIGHT : '{}'".format(frame_height))
print("CAP_PROP_FPS : '{}'".format(fps))

# Check if camera opened successfully
if capture.isOpened()is False:
    print("Error opening the camera")
    
while capture.isOpened():
    ret, frame = capture.read()

    if ret is True:
        cv2.imshow('Input frame from the camera', frame)
        if cv2.waitKey(20) & 0xFF == ord('q'):
            break
    else:
        break
        
capture.release()
cv2.destroyAllWindows()
复制代码

执行此脚本将会打印如下属性信息:

CV_CAP_PROP_FRAME_WIDTH: '640.0'
CV_CAP_PROP_FRAME_HEIGHT : '480.0'
CAP_PROP_FPS : '30.0'
复制代码

保存相机画面

可以修改前面的示例以在处理流程中添加其他的功能。例如,我们可能想将一些关键的感兴趣帧保存到磁盘中。在以下示例 read_camera_capture.py 中 ,将添加此示例功能,当按下键盘上的 c 键时,将当前帧保存到磁盘(同时保存 BGR 和灰度帧):

import cv2
import argparse

capture = cv2.VideoCapture(0)
if capture.isOpened() is False:
    print("Error opening the camera")
frame_index = 0
while capture.isOpened():
    ret, frame = capture.read()

    if ret is True:
        gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        # 保存相机画面
        if cv2.waitKey(20) & 0xFF == ord('c'):
            frame_name = "camera_frame_{}.png".format(frame_index)
            gray_frame_name = "grayscale_camera_frame_{}.png".format(frame_index)
            # 将当前帧保存到磁盘(同时保存 BGR 和灰度帧)
            cv2.imwrite(frame_name, frame)
            cv2.imwrite(gray_frame_name, gray_frame)
            frame_index += 1
        if cv2.waitKey(20) & 0xFF == ord('q'):
            break
    else:
        break

capture.release()
cv2.destroyAllWindows()
复制代码

当按下 c 键时,首先构造两个文件名;然后,将两个图像保存到磁盘;最后,frame_index 递增,以便为保存下一帧做好准备。

读取视频文件

cv2.VideoCapture 也可以用于读取视频文件,要读取视频文件,应在创建 cv2.VideoCapture 对象时提供视频文件的路径,编写 read_video_file.py 脚本:

import cv2
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("video_path", help="path to the video file")
args = parser.parse_args()
capture = cv2.VideoCapture(args.video_path)
if capture.isOpened() is False:
    print("Error opening the video file!")

while capture.isOpened():
    ret, frame = capture.read()
    if ret is True:
        cv2.imshow('Original frame from the video file', frame)
        gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        cv2.imshow('Grayscale frame', gray_frame)
        if cv2.waitKey(20) & 0xFF == ord('q'):
            break
    else:
        break
capture.release()
cv2.destroyAllWindows()
复制代码

通过在命令行中执行以下命令,运行脚本:

python read_video_file.py xinlingqilv.mp4
复制代码

可以看到运行结果开始播放视频文件:

在这里插入图片描述

相关链接

OpenCV图像处理基础

OpenCV中的坐标系与图像通道顺序

OpenCV读取和修改图像像素值

OpenCV图像的读取与写入

猜你喜欢

转载自juejin.im/post/7055854941876781087