← 返回首页
OpenCV播放视频
发表时间:2025-03-09 15:02:04
OpenCV播放视频

OpenCV不仅提供了丰富的图像处理功能,还能够帮助我们轻松实现视频的加载、播放以及各种控制。

1.用摄像头捕获视频

通常,我们必须用摄像头捕捉实时流。OpenCV提供了一个非常简单的接口。让我们从摄像头中捕捉视频(我正在使用笔记本电脑的内置摄像头),将其转换为灰度视频并显示。只是一个简单的任务开始。

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

import cv2
import tkinter as tk
from functools import partial

def capture_video():
    # 打开默认摄像头(索引0)
    cap = cv2.VideoCapture(0)

    # 检查摄像头是否成功打开
    if not cap.isOpened():
        print("无法打开摄像头")
        return

    # 创建一个窗口
    cv2.namedWindow("mycamera", cv2.WINDOW_NORMAL)

    # 获取屏幕分辨率
    root = tk.Tk()
    screen_width = root.winfo_screenwidth()
    screen_height = root.winfo_screenheight()
    root.destroy()

    # 获取视频窗口的大小
    ret, frame = cap.read()
    if ret:
        frame_height, frame_width = frame.shape[:2]
    else:
        frame_width, frame_height = 640, 480  # 默认值

    # 计算窗口位置,使其居中
    window_x = (screen_width - frame_width) // 2
    window_y = (screen_height - frame_height) // 2

    # 设置窗口位置
    cv2.moveWindow("mycamera", window_x, window_y)

    while True:
        # 从摄像头读取帧
        ret, frame = cap.read()

        # 如果读取帧失败,退出循环
        if not ret:
            break

        # 显示彩色帧
        cv2.imshow("mycamera", frame)

        # 检测是否按下了关闭窗口的按键(例如,点击窗口的关闭按钮)
        if cv2.waitKey(1) & 0xFF == 27:  # 按下ESC键也可以退出
            break

        # 检查是否关闭了窗口
        if cv2.getWindowProperty("mycamera", cv2.WND_PROP_VISIBLE) < 1:
            break

    # 释放摄像头资源并关闭所有OpenCV窗口
    cap.release()
    cv2.destroyAllWindows()

if __name__ == "__main__":
    capture_video()

2.从文件中播放视频

把设备索引号改成文件名即可。在播放每一帧时,使用cv2.waitKey()适当持续时间,如果它太少,视频会非常快,如果它太高,视频会很慢(那么,这是如何以慢动作显示视频)。正常情况下,25-28ms即可。

以下是OpenCV播放视频的函数封装。该函数提供了两个参数:第一参数是播放视频的路径,第二个参数是播放视频的缩放比率。

import cv2


def play_video(video_path, scale_factor):
    """
    使用 OpenCV 播放视频文件,并支持缩放功能。

    参数:
        video_path (str): 视频文件的路径。
        scale_factor (float): 视频帧的缩放比例,大于0的浮点数。
    """
    # 检查缩放比例是否有效
    if scale_factor <= 0:
        raise ValueError("缩放比例必须大于0")

    # 打开视频文件
    cap = cv2.VideoCapture(video_path)

    # 检查视频是否成功打开
    if not cap.isOpened():
        print(f"无法打开视频文件: {video_path}")
        return

    try:
        while True:
            # 读取视频帧
            ret, frame = cap.read()

            # 如果读取帧失败,退出循环
            if not ret:
                break

            # 对帧进行缩放
            resized_frame = cv2.resize(frame, None, fx=scale_factor, fy=scale_factor, interpolation=cv2.INTER_LINEAR)

            # 显示缩放后的帧
            cv2.imshow('Video Player', resized_frame)


            """
            # 按下 'q' 键退出播放
            if cv2.waitKey(25) & 0xFF == ord('q'):
                break
            """

            # 检测是否按下了关闭窗口的按键(例如,点击窗口的关闭按钮)
            if cv2.waitKey(28) & 0xFF == 27:  # 按下ESC键也可以退出
                break

            # 检查是否关闭了窗口
            if cv2.getWindowProperty("Video Player", cv2.WND_PROP_VISIBLE) < 1:
                break
    finally:
        # 释放视频对象和窗口
        cap.release()
        cv2.destroyAllWindows()


# 使用示例
# play_video('your_video.mp4', 0.5)  # 将视频缩小为原来的一半

if __name__ == '__main__':
    video_path = './video/nvidia01.mp4'
    scale_factor = 0.5
    play_video(video_path, scale_factor)

OpenCV本身并不支持音频播放功能,它主要用于处理视频帧和图像。要实现带有声音的视频播放,你需要使用其他库来处理音频部分,例如 pygame 或 sounddevice 等。

首先安装pygame库。

pip install pygame 

以下是一个结合 OpenCV 和 pygame的示例代码,用于播放视频并同时播放音频。

import cv2
import pygame
import threading


def play_audio(audio_path):
    """
    播放音频文件
    """
    pygame.init()

    # 加载 MP3 文件
    pygame.mixer.music.load(audio_path)

    # 播放音频
    pygame.mixer.music.play()

    while pygame.mixer.music.get_busy():
        pygame.time.Clock().tick(10)

    pygame.quit()


def play_video_with_audio(video_path, scale_factor, audio_path=None):
    """
    使用 OpenCV 播放视频文件,并支持缩放功能,同时播放音频。

    参数:
        video_path (str): 视频文件的路径。
        scale_factor (float): 视频帧的缩放比例,大于0的浮点数。
        audio_path (str, optional): 音频文件的路径。如果为None,则不播放音频。
    """
    # 检查缩放比例是否有效
    if scale_factor <= 0:
        raise ValueError("缩放比例必须大于0")

    # 打开视频文件
    cap = cv2.VideoCapture(video_path)

    # 检查视频是否成功打开
    if not cap.isOpened():
        print(f"无法打开视频文件: {video_path}")
        return

    # 如果提供了音频路径,则启动音频播放线程
    if audio_path:
        audio_thread = threading.Thread(target=play_audio, args=(audio_path,))
        audio_thread.daemon = True
        audio_thread.start()

    try:
        while True:
            # 读取视频帧
            ret, frame = cap.read()

            # 如果读取帧失败,退出循环
            if not ret:
                break

            # 对帧进行缩放
            resized_frame = cv2.resize(frame, None, fx=scale_factor, fy=scale_factor, interpolation=cv2.INTER_LINEAR)

            # 显示缩放后的帧
            cv2.imshow('Video Player', resized_frame)

            """
            # 按下 'q' 键退出播放
            if cv2.waitKey(25) & 0xFF == ord('q'):
                break
            """

            if cv2.waitKey(28) & 0xFF == 27:  # 按下ESC键也可以退出
                break

            # 检查是否关闭了窗口
            if cv2.getWindowProperty("Video Player", cv2.WND_PROP_VISIBLE) < 1:
                break
    finally:
        # 释放视频对象和窗口
        cap.release()
        cv2.destroyAllWindows()

# 使用示例

if __name__ == '__main__':
    play_video_with_audio('./video/nvidia01.mp4', 0.5, './video/nvidia01.MP3')

注意事项: - pygame 需要 ffmpeg 来处理音频文件。如果你的系统中没有安装 ffmpeg,可能需要单独安装它。 - 音频和视频的同步可能会有问题,尤其是在不同硬件和操作系统上。如果需要更精确的同步,可能需要更复杂的处理逻辑。 - 如果视频不包含音轨,你需要用专业的视频处理工具,把音轨部分分离出来,单独保存为MP3文件。 - 如果视频文件本身包含音频轨道,你可以直接提取音频部分进行播放,而无需单独提供音频文件。

3.保存视频

所以我们拍摄一个视频,逐帧处理,我们要保存视频。对于图像来说,这非常简单,只是使用cv2.imwrite()。 但是视频需要更多的工作。

创建一个VideoWrite的对象,确定输出文件名,指定FourCC编码,播放频率和帧的大小,最后是isColor标签True为彩色。 FourCC是一个4字节码,用来确定视频的编码格式。

  1. In Fedora : DIVX , XVID , MJPG , X264 , WMV1 , WMV2 XVID是最好的,MJPG是高尺寸视频,X264得到小尺寸视频
  2. In Windows : DIVX
  3. In OSX :不知道用什么好 设置FourCC格式时,原文里采用了·cv2.VideoWriter_fourcc()·这个函数,若运行程序的时候显示这个函数不存在,可以改用了·cv2.cv.CV_FOURCC·这个函数。
import numpy as np
import cv2

cap = cv2.VideoCapture(0)

# Define the codec and create VideoWriter object
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)

        # 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()