0

0

OpenCV VideoWriter 常见陷阱:如何避免生成空视频文件

聖光之護

聖光之護

发布时间:2025-08-14 18:48:01

|

457人浏览过

|

来源于php中文网

原创

OpenCV VideoWriter 常见陷阱:如何避免生成空视频文件

本文深入探讨了使用 OpenCV VideoWriter 模块生成视频时常见的“空文件”问题。核心原因在于 VideoWriter 的 frameSize 参数误将图像的 (height, width) 顺序传递为 (width, height)。教程将详细解释 VideoWriter 的正确用法、参数配置,并通过示例代码演示如何避免此陷阱,确保成功创建可播放的视频文件。

OpenCV VideoWriter 详解

opencv 提供了 cv2.videowriter 类,用于将一系列图像帧写入视频文件。它是图像处理和计算机视觉应用中创建视频输出的关键工具。正确理解和配置其参数对于生成有效的视频文件至关重要。

cv2.VideoWriter 的构造函数通常接收以下参数:

  • filename: 输出视频文件的路径和名称(例如 "output.mp4")。
  • fourcc: 视频编解码器。这是一个四字符代码(FourCC),用于指定视频流的压缩格式。例如,cv2.VideoWriter_fourcc(*'XVID') 或 cv2.VideoWriter_fourcc(*'mp4v')。不同的操作系统和 OpenCV 版本可能支持不同的编解码器,并且编解码器与文件容器(如 .mp4, .avi, .mkv)之间存在兼容性要求。
  • fps: 视频的帧率(每秒帧数)。
  • frameSize: 视频帧的尺寸,通常是一个 (width, height) 的元组或列表。这是本文要重点讨论的关键参数。
  • isColor: 可选参数,布尔值,表示视频是否为彩色。默认为 True。如果为 False,则表示灰度视频。

创建 VideoWriter 对象后,可以使用 write() 方法逐帧写入图像,并在所有帧写入完毕后调用 release() 方法释放资源并完成文件写入。

核心问题:frameSize 参数的陷阱

在实际应用中,许多开发者在使用 cv2.VideoWriter 时会遇到一个令人困惑的问题:代码运行没有报错,也生成了视频文件,但文件大小极小(通常只有几百字节),且无法正常播放。通过媒体信息工具检查,文件结构似乎不完整,例如 VLC 播放器可能会提示“无法找到任何集群或章节”。

这个问题的根本原因在于 frameSize 参数的误用。当从图像(如 NumPy 数组)获取尺寸时,我们通常习惯于 img.shape 返回 (height, width, channels) 的顺序。然而,cv2.VideoWriter 的 frameSize 参数却明确要求 (width, height) 的顺序。

错误示例:

假设你有一张尺寸为 120 像素高 x 160 像素宽的图片。当你读取这张图片并检查其 shape 时,你会得到 (120, 160, 3) (对于彩色图片)。如果直接将 (120, 160) 作为 frameSize 传递给 VideoWriter,即:

Cogram
Cogram

使用AI帮你做会议笔记,跟踪行动项目

下载
import cv2

# 假设图片尺寸是 160宽 x 120高
# 错误地将 (height, width) 传递给 frameSize
fourcc = cv2.VideoWriter.fourcc(*'x264')
# 错误的 frameSize: [120, 160] (实际是 height, width)
writer = cv2.VideoWriter("py_test_error.mkv", fourcc, 60.0, [120, 160])

def record_error(writer_obj):
  for i in range(121):
    img = cv2.imread(f"capture.{i}.jpg") # 假设图片是 160x120
    if img is None:
        print(f"Error: Could not read image capture.{i}.jpg")
        continue
    writer_obj.write(img)

record_error(writer)
writer.release() # 释放资源
print("视频文件生成完毕,但可能为空。")

在这种情况下,VideoWriter 期望的帧尺寸是 120 像素宽 x 160 像素高,而你实际写入的图像是 160 像素宽 x 120 像素高。尺寸不匹配导致 VideoWriter 无法正确处理帧数据,从而生成一个空的或损坏的视频文件。

完整解决方案与示例代码

解决这个问题的关键在于确保 frameSize 参数的值严格遵循 (width, height) 的顺序,并且与你实际写入的图像帧的尺寸相匹配。

正确示例:

如果你的图片是 160 像素宽 x 120 像素高,那么 frameSize 应该设置为 [160, 120]。

import cv2
import os

# 假设当前目录下有 capture.0.jpg 到 capture.120.jpg 共121张图片
# 这些图片尺寸均为 160宽 x 120高

def record_frames(writer_obj):
  for i in range(121):
    img_path = f"capture.{i}.jpg"
    img = cv2.imread(img_path)
    if img is None:
        print(f"警告: 无法读取图像 {img_path},跳过此帧。")
        continue
    # 确保写入的图像尺寸与 VideoWriter 期望的 frameSize 一致
    writer_obj.write(img)
  print("所有图像帧已写入。")

# 1. 定义输出文件路径和编解码器
output_filename = "py_test_correct.mkv"
# 推荐使用 'mp4v' 或 'XVID' 对于 .mp4/.avi 容器,
# 'x264' 对于 .mkv 容器通常效果更好,但需要系统支持。
fourcc = cv2.VideoWriter.fourcc(*'x264')

# 2. 定义帧率
fps = 60.0

# 3. 定义正确的帧尺寸:(宽度, 高度)
# 假设图片是 160宽 x 120高
frame_width = 160
frame_height = 120
frame_size = (frame_width, frame_height)

# 4. 创建 VideoWriter 对象
try:
    writer = cv2.VideoWriter(output_filename, fourcc, fps, frame_size)
    if not writer.isOpened():
        print(f"错误: 无法打开视频写入器。请检查编解码器和文件路径。")
    else:
        print(f"成功创建 VideoWriter 对象,准备写入 {output_filename}")
        # 5. 写入所有帧
        record_frames(writer)
        print(f"视频文件 '{output_filename}' 生成完毕。")

except Exception as e:
    print(f"发生异常: {e}")
finally:
    # 6. 释放 VideoWriter 资源,确保文件被正确写入和关闭
    if 'writer' in locals() and writer.isOpened():
        writer.release()
        print("VideoWriter 资源已释放。")

在上述代码中,frame_size = (frame_width, frame_height) 确保了 VideoWriter 接收到的是正确的宽度和高度顺序,从而解决了生成空文件的问题。

注意事项与最佳实践

  1. writer.release() 的重要性: 无论视频写入成功与否,务必在所有帧写入完毕后调用 writer.release()。这个方法会关闭文件句柄,刷新缓冲区,并完成视频文件的最终写入。如果忘记调用,即使代码没有报错,生成的视频文件也可能损坏或无法播放。将其放在 finally 块中是良好的编程习惯,确保即使发生异常也能被调用。
  2. fourcc 编解码器与容器的兼容性:
    • 不同的编解码器 (fourcc) 与文件容器(.mp4, .avi, .mkv 等)之间存在兼容性。例如,'mp4v' 和 'XVID' 通常用于 .mp4 或 .avi 文件,而 'x264' 更常用于 .mkv 或 .mp4 (如果系统支持 H.264 编码)。
    • 如果 fourcc 不受系统支持或与容器不兼容,writer.isOpened() 可能会返回 False,或者生成的文件无法播放。在 Linux 系统上,确保安装了 ffmpeg 或 gstreamer 等后端库,因为 OpenCV 依赖它们进行视频编解码。
    • 尝试不同的 fourcc 代码和文件扩展名组合,直到找到一个适合你系统和需求的。常见的 FourCCs 包括:
      • `*'mp

相关专题

更多
磁盘配额是什么
磁盘配额是什么

磁盘配额是计算机中指定磁盘的储存限制,就是管理员可以为用户所能使用的磁盘空间进行配额限制,每一用户只能使用最大配额范围内的磁盘空间。php中文网为大家提供各种磁盘配额相关的内容,教程,供大家免费下载安装。

1345

2023.06.21

如何安装LINUX
如何安装LINUX

本站专题提供如何安装LINUX的相关教程文章,还有相关的下载、课程,大家可以免费体验。

698

2023.06.29

linux find
linux find

find是linux命令,它将档案系统内符合 expression 的档案列出来。可以指要档案的名称、类别、时间、大小、权限等不同资讯的组合,只有完全相符的才会被列出来。find根据下列规则判断 path 和 expression,在命令列上第一个 - ( ) , ! 之前的部分为 path,之后的是 expression。还有指DOS 命令 find,Excel 函数 find等。本站专题提供linux find相关教程文章,还有相关

293

2023.06.30

linux修改文件名
linux修改文件名

本专题为大家提供linux修改文件名相关的文章,这些文章可以帮助用户快速轻松地完成文件名的修改工作,大家可以免费体验。

773

2023.07.05

linux系统安装教程
linux系统安装教程

linux系统是一种可以免费使用,自由传播,多用户、多任务、多线程、多CPU的操作系统。本专题提供linux系统安装教程相关的文章,大家可以免费体验。

571

2023.07.06

linux查看文件夹大小
linux查看文件夹大小

Linux是一种自由和开放源码的类Unix操作系统,存在着许多不同的Linux版本,但它们都使用了Linux内核。Linux可安装在各种计算机硬件设备中,比如手机、平板电脑、路由器、视频游戏控制台、台式计算机、大型机和超级计算机。linux怎么查看文件夹大小呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

544

2023.07.20

linux查看ip命令
linux查看ip命令

本专题为大家提供linux查看ip命令相关文章内容,感兴趣的朋友可以免费下载体验试试。

296

2023.07.20

linux查看cpu使用率
linux查看cpu使用率

在linux的系统维护中,可能需要经常查看cpu使用率,分析系统整体的运行情况。本专题为大家带来了linux查看cpu使用率的相关文章,感兴趣的朋友千万不要错过了。

374

2023.07.25

桌面文件位置介绍
桌面文件位置介绍

本专题整合了桌面文件相关教程,阅读专题下面的文章了解更多内容。

0

2025.12.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 6.2万人学习

Git 教程
Git 教程

共21课时 | 2.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号