AI视觉算法中的OpenCV API (二)

视频写入 (FourCC, VideoWriter)​

1. VideoWriter_fourcc - 视频编码器四字符代码

# OpenCV 3.x, 4.x
fourcc = cv2.VideoWriter_fourcc('M','J','P','G')fourcc = cv2.VideoWriter_fourcc(*'H264')fourcc = cv2.VideoWriter_fourcc(*'MJPG')
  • FourCC: 代表 ​Four ​Character ​Code,是一个4字节的代码,用于指定视频流的编码格式(Codec)​。它决定了视频数据如何被压缩。
  • 定义一个视频编码器(Codec)。视频编码器负责将连续的图像帧压缩成视频流,显著减小文件大小。

常用 FourCC 代码

  • Video Codecs by FOURCC - fourcc.org
  • ​**'XVID'​: MPEG-4 编码器。兼容性好,文件大小适中,是最常用**的选择之一。
  • ​**'MJPG'**​: Motion-JPEG 编码器。质量高,但文件非常大。
  • ​**'H264'​: H.264/AVC 编码器。压缩效率极高(文件小),质量好。​需要系统安装 H.264 编码器支持**​(如 Windows 上的 OpenH264 或 x264)。
  • ​**'MP4V'**​: MPEG-4 视频编码器。常用于 .mp4 文件。
  • ​**'AVC1'**​: 另一种表示 H.264 的方式。
  • ​**'DIVX'**​: DivX 编码器(基于 MPEG-4)。

常用 FourCC 代码与推荐的文件扩展名对应表

  • 文件扩展名​: 如 .avi.mp4.mov,用于指定容器格式(Container)​。容器是一个“包装盒”,里面可以存放由特定编码器压缩的视频流、音频流、字幕等信息。
  • 关键点在于:FourCC 编码器和文件扩展名容器之间并没有严格的、一对一的强制绑定关系,但存在广泛认可和兼容的“最佳实践”组合。​
  • 选择一个不常见的组合(例如,在 .mp4 文件里使用 XVID 编码)可能会导致某些播放器无法识别或播放。
FourCC 代码推荐文件扩展名说明与常见用途
​**'XVID'**​.avi最常用、兼容性最好的组合之一。XVID 是一个开源的 MPEG-4 视频编码器,生成的 .avi 文件可以在绝大多数设备和播放器上播放。文件大小和质量平衡得很好。
​**'MJPG'**​.aviMotion-JPEG 编码,将每一帧都压缩为一张 JPEG 图片。​视频质量很高,但文件体积非常大。常用于对质量要求极高且不介意文件大小的场景。
​**'H264'**​.mp4H.264/AVC 编码,​当今最流行的编码标准。压缩效率极高(在相同质量下文件更小)。​注意​:OpenCV 可能需要系统安装额外的开源库(如 OpenH264 或 x264)才能使用此编码器。
​**'AVC1'**​.mp4本质上是 H.264 编码的另一种表示方法。行为与 'H264' 类似。
​**'MP4V'**​.mp4代表 MPEG-4 视频(Part 2),与 H.264(Part 10)不同。压缩效率通常不如 H.264,但兼容性可能更好。
​**'DIVX'**​.aviDivX 编码器(也是基于 MPEG-4)。曾非常流行,现在多用于历史遗留项目。
​**'FMP4'**​.mp4FFmpeg 的 MPEG-4 编码器。如果你的 OpenCV 编译时包含了 FFmpeg 支持,可能会用到。
​**'PIM1'**​.aviMPEG-1 编码。非常老的格式,文件大,质量一般,现较少使用。
​**'X264'**​.mp4特指使用 x264 库(一个优秀的开源 H.264 编码器实现)。这通常需要从源码自定义编译 OpenCV 才能直接使用。

选择建议​:

  • 为了最大兼容性​:使用 ​**'XVID'​ + ​.avi**。这是 OpenCV 中最可靠、问题最少的输出组合,几乎总能成功。
  • 为了更小的文件​:使用 ​**'H264'​ 或'AVC1' + ​.mp4**。这是目前网络传输和存储的标准格式。但需要确保你的 OpenCV 环境支持它(否则会写入失败或生成空文件)。
  • 高质量,不介意文件大小:'MJPG' + .avi**。

最重要的步骤​:

在编写代码时,始终检查 VideoWriter 对象是否通过 isOpened() 方法成功打开。如果首选的高效编码器(如 H.264)不可用,则回退到兼容性更好的编码器(如 XVID)。这是一种良好的编程实践,可以增强代码的健壮性。

fourcc = cv2.VideoWriter_fourcc(*'H264')
out = cv2.VideoWriter('test.mp4', fourcc, 20.0, (640, 480))
if not out.isOpened():print("错误:无法使用 H264 编码器!将回退到 XVID。")fourcc = cv2.VideoWriter_fourcc(*'XVID')out = cv2.VideoWriter('test.avi', fourcc, 20.0, (640, 480))

2. VideoWriter - 视频写入器

  • 创建一个对象,用于将连续的图像帧写入视频文件。
out = cv2.VideoWriter(filename, fourcc, fps, frame_size[, isColor])

语法:

  • filename: 要保存的视频文件路径(包括扩展名,如 'output.avi' 或 'result.mp4')。
  • fourcc: 由 VideoWriter_fourcc 创建的编码器对象。
  • fps: 视频的帧率(每秒帧数)。应与输入源(如摄像头或视频文件)的帧率匹配或根据需求设定。
  • frame_size: 视频帧的尺寸,以元组形式表示 (width, height)。​必须与你要写入的每一帧图像的尺寸完全一致!​
  • isColor (可选): 指定是否为彩色视频。默认为 True。如果写入灰度帧,设为 False 可能更高效。

核心方法​:

  • ​**out.write(frame)**​: 将一帧图像(frame,一个 NumPy 数组)写入视频文件。这是循环中最常用的方法。
  • ​**out.release()​: ​非常重要!​**​ 在完成所有帧的写入后,必须调用此方法来正确关闭视频文件,释放资源并确保文件完整可播。忘记调用会导致视频文件损坏或无法播放。

3. 完整工作流程示例

import cv2# 1. 打开摄像头 (输入源)
cap = cv2.VideoCapture(0)  # 0 表示默认摄像头# 2. 获取摄像头参数 (用于设置VideoWriter)
fps = cap.get(cv2.CAP_PROP_FPS)  # 获取摄像头帧率
# 如果摄像头返回0,设置一个合理的帧率 (如20)
if fps <= 0:fps = 20.0
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))  # 获取帧宽度
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))  # 获取帧高度
frame_size = (width, height)# 3. 定义视频编码器 (FourCC) 和创建 VideoWriter 对象 (输出)
fourcc = cv2.VideoWriter_fourcc(*'XVID')  # 使用XVID编码器, 注意 '*' 解包
# 创建输出文件 'output.avi'
out = cv2.VideoWriter('output.avi', fourcc, fps, frame_size)# 4. 循环处理每一帧
while cap.isOpened():# 读取一帧ret, frame = cap.read()if not ret:print("无法从摄像头读取帧!")break# 例如:将帧转换为灰度图 (实际项目中替换为你的AI模型推理)processed_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 5. 将处理后的帧写入输出视频文件out.write(processed_frame)  # 写入处理后的帧# 6. (可选) 在本地显示结果cv2.imshow('Processed Video', processed_frame)# 按 'q' 键退出if cv2.waitKey(1) & 0xFF == ord('q'):break# 7. 释放资源 (非常重要!)
cap.release()  # 释放摄像头
out.release()  # 释放VideoWriter,确保文件正确关闭
cv2.destroyAllWindows()  # 关闭所有窗口
print("视频已保存为 'output.avi'")

4.详解 cv2.waitKey(1):图像刷新与键盘输入的完美结合

  • cv2.waitKey(1) 是 OpenCV 图像处理中一个看似简单但极其重要的函数,它在实时应用中扮演着关键角色。
  • 函数原型:
  • retval = cv2.waitKey([, delay])
  • 参数:
  • delay: 等待键盘事件的时间(以毫秒为单位)。默认值为0。
  • 返回值:
  • retval: 返回按下的键的ASCII码值。如果没有按键被按下,则返回-1。

4.1 ​图像窗口刷新机制

  • cv2.waitKey() 是 OpenCV 窗口系统的事件处理核心
  • 调用此函数会强制刷新所有通过 cv2.imshow() 显示的窗口
  • 没有这个调用,窗口会显示为灰色或显示旧内容,无法更新为最新图像帧

4.2  ​键盘事件检测

  • 函数会检测并返回最近按下的按键的 ASCII 码值
  • 参数 1 表示等待时间为 ​1 毫秒,这是一个非阻塞式等待
  • 在等待期间,它会检查是否有按键事件发生

4.3 waitKey(0) - 无限等待

  • 程序会暂停,直到用户按下任意键
  • 常用于静态图像显示场景
  • 示例:显示一张图片后等待用户按键关闭窗口

4.4 waitKey(1) - 短时等待(推荐用于实时应用)

  • 等待 ​1 毫秒后继续执行
  • 在等待期间检查按键事件
  • 保持程序流畅运行的同时响应按键
  • 最佳实践​:在视频处理循环中使用

4.4  waitKey(25) - 控制帧率

  • 等待 25 毫秒 ≈ 40 FPS (1000ms/25ms)
  • 可用于控制视频播放速度

4.5 & 0xFF

  • waitKey() 返回的是 ​32 位整数
  • 在 64 位系统上,高位可能包含无关数据
  • & 0xFF 操作只保留最低的 8 位(一个字节)
  • 确保我们只获取有效的 ASCII 码值

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/922113.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/922113.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

分享| 2025年版AIGC数字人实验室解决方案教学资源解析

AIGC数字人实验室解决方案构建了涵盖基础层、平台环境层与资源层的多层次教学架构&#xff0c;依托150平方米的实体空间与60人并行授课的规模化支持&#xff0c;为学生提供了技术实践与创新的高效平台。其教学资源体系覆盖AIGC文本生成、图像生成、数字人应用与智能体开发四大核…

内存大(巨)页

一、大&#xff08;巨&#xff09;页 大&#xff08;巨&#xff09;页&#xff0c;很好理解&#xff0c;就是的大的页。说这个大页前&#xff0c;得先把计算机中内存的管理简单说明一下&#xff0c;否则可能对于一些新手或者把操作系统中内存管理的方法的开发者不太友好。最早的…

langgraph astream使用详解

langgraph中graph的astream&#xff08;stream&#xff09;方法分别实现异步&#xff08;同步&#xff09;流式应答&#xff0c;在langgraph-api服务也是核心方法&#xff0c;实现与前端的对接&#xff0c;必须要把这个方法弄明白。该方法中最重要的参数是stream_mode&#xff…

【C++】模板进阶:非类型参数、模板特化与分离编译

目录 1. 非类型模板参数 2. 模板的特化 3. 分离编译 1. 非类型模板参数 模板参数分类类型形参与非类型形参。 类型形参即&#xff1a;出现在模板参数列表中&#xff0c;跟在class或者typename之类的参数类型名称。 非类型形参&#xff0c;就是用一个常量作为类(函数)模板…

栈-1047.删除字符串中的所有相邻重复项-力扣(LeetCode)

一、题目解析 1、反复执行重复项删除操作 2、s仅由小写英文字母组成 二、算法原理 该题并不难&#xff0c;难的是能不能想到用栈这个数据结构解题 解法&#xff1a;栈模拟 横着看起来不好理解&#xff0c;我们把它竖起来&#xff0c;是不是和消消乐很类似&#xff0c;两两消…

【每日算法】移除元素 LeetCode

双指针方法是解决数组或链表问题中非常高效的技巧之一&#xff0c;尤其适用于原地修改数组或减少时间复杂度的场景。以下是对双指针方法的详细讲解。1. 双指针方法的核心思想双指针方法通常使用两个指针&#xff08;或索引&#xff09;在数组或链表中协同工作&#xff0c;通过一…

Android 项目:画图白板APP开发(六)——分页展示

本篇将介绍如何为我们的画板应用添加分页展示功能&#xff0c;让用户可以创建多个画布并在它们之间轻松切换。这章没有啥知识点的讲解&#xff0c;主要介绍一下每页保存的数据结构是什么样的。 一、ListView 多页数据的管理我们使用ListView。之前有文章讲过ListView这里就不多…

智能眼镜产品成熟度分析框架与评估

引言 当前(2025年9月12日),智能眼镜(Smart Glasses)市场正处于快速演进阶段,从早期的新奇设备向主流消费电子转型。AI整合、AR显示和多模态交互的进步推动了这一转变。根据最新数据,2025年AI眼镜发货量预计达686万台,同比增长265%,全球市场规模从2024年的约19.3亿美元…

(网络编程)网络编程套接字 UDP的socket API 代码解析

网络编程基础 为什么需要网络编程?--丰富的网络资源 用户在浏览器中,打开在线视频网站,如优酷看视频,实质是通过网络,获取到网络上的一个视频资源。与本地打开视频文件类似,只是视频文件这个资源的来源是网络。 相比本地资源来说,网络提供了更为丰富的网络资源:所谓的网络资源…

【STM32】状态机(State Machine)

这篇博客介绍 状态机&#xff08;State Machine&#xff09;&#xff0c;适合用于嵌入式开发、驱动开发、协议解析、按键识别等多种场景。 一、什么是状态机&#xff08;State Machine&#xff09;&#xff1f; 状态机&#xff08;State Machine&#xff09;是一种用于描述系统…

深度学习在离岗检测中的应用

离岗检测技术正逐步成为现代企业精细化管理和安全生产的重要工具。这项基于计算机视觉和人工智能的应用&#xff0c;通过自动化、实时化的监测方式&#xff0c;有效提升了工作纪律性和运营效率&#xff0c;为项目管理者和企业提供了创新的监管解决方案。在许多工作场景中&#…

Spring缓存(二):解决缓存雪崩、击穿、穿透问题

1. 缓存穿透问题与解决方案 1.1 什么是缓存穿透 缓存穿透是指查询一个不存在的数据&#xff0c;由于缓存中没有这个数据&#xff0c;每次请求都会直接打到数据库。 如果有恶意用户不断请求不存在的数据&#xff0c;就会给数据库带来巨大压力。 这种情况下&#xff0c;缓存失去了…

PHP 与 WebAssembly 的 “天然隔阂”

WebAssembly&#xff08;简称 WASM&#xff09;是一种低级二进制指令格式&#xff0c;旨在为高级语言提供高性能的编译目标&#xff0c;尤其在浏览器环境中实现接近原生的执行效率。它主要用于前端性能密集型场景&#xff08;如游戏引擎、视频编解码、3D 渲染等&#xff09;&am…

unity中通过拖拽,自定义scroll view中子物体顺序

1.在每个content的子物体上挂载DragHandler脚本&#xff0c;并且添加Canvs Group组件&#xff0c;设置见图2.DragHandler脚本内容&#xff1a;using UnityEngine; using UnityEngine.UI; using UnityEngine.EventSystems; using System.Collections.Generic; using System.Coll…

用 Matplotlib 绘制饼图:从基础语法到实战美化,全面掌握分类数据可视化技巧

用 Matplotlib 绘制饼图:从基础语法到实战美化,全面掌握分类数据可视化技巧 在数据分析与可视化的世界里,**“图胜千言”**早已成为共识。而在众多图表类型中,饼图(Pie Chart)以其直观的比例展示方式,成为展示分类数据分布的常见选择。无论是业务报表、用户画像,还是市…

基础算法之二分算法 --- 2

大家好&#xff0c;不同的时间&#xff0c;相同的地点&#xff0c;时隔多日我们又见面了。继上次的二分算法后&#xff0c;我们这次要来学习的是二分答案了。这个部分相较于前面的二分算法难度有相当的提升&#xff0c;希望大家有所准备。虽然难度增加了&#xff0c;但是博主还…

发挥nano banana的最大能力

1. 概述Nano Banana 简介&#xff1a;Nano Banana 是 Google DeepMind 开发的 AI 图像生成与编辑模型&#xff0c;集成在 Google Gemini 平台中&#xff08;具体为 Gemini 2.5 Flash 版本&#xff09;。它以高效的图像编辑能力闻名&#xff0c;尤其在角色一致性、光影理解和快速…

leetcode 面试题01.02判定是否互为字符重排

一、问题描述二、解题思路解法一&#xff1a;对s1和s2进行sort排序&#xff0c;返回s1是否等于s2&#xff1b;解法二&#xff1a;用哈希表分别来记录s1和s2中字符出现的次数&#xff0c;统计完后&#xff0c;判断两个哈希表是否相等;三、代码实现解法一&#xff1a;时间复杂度&…

Python Yolo8 物体识别

支持单张图片/图片目录批量预标注 默认使用cuda GPU .env HTTP_PROXYhttp://192.168.2.109:10808 HTTPS_PROXYhttp://192.168.2.109:10808pyproject.toml [project] name "yolo-test" version "0.1.0" description "Add your description here&quo…

LeetCode100-234回文链表

本文基于各个大佬的文章上点关注下点赞&#xff0c;明天一定更灿烂&#xff01;前言Python基础好像会了又好像没会&#xff0c;所有我直接开始刷leetcode一边抄样例代码一边学习吧。本系列文章用来记录学习中的思考&#xff0c;写给自己看的&#xff0c;也欢迎大家在评论区指导…