调整视频帧率、分辨率

v1.0
问题:人脸检测太灵敏了,导致当画面中出现多个人脸时,画面反复跳各个人脸,闪动严重

import cv2
import os
from tqdm import tqdm  # 进度条
import subprocess# 加载人脸检测模型
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')def contains_face(frame):gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)faces = face_cascade.detectMultiScale(gray, 1.3, 5)return len(faces) > 0def crop_center(frame, crop_width, crop_height):height, width = frame.shape[:2]start_x = width//2 - crop_width//2start_y = height//2 - crop_height//2return frame[start_y:start_y+crop_height, start_x:start_x+crop_width]def extract_audio(input_path, audio_path):subprocess.run(['ffmpeg', '-y', '-i', input_path, '-vn', '-acodec', 'copy', audio_path])def merge_video_audio(video_path, audio_path, output_path):subprocess.run(['ffmpeg', '-y', '-i', video_path, '-i', audio_path, '-c:v', 'copy', '-c:a', 'aac', '-map', '0:v:0', '-map', '1:a:0', output_path])def process_video(path, out_path, fps=25):print(f'[INFO] ===== process video from {path} to {out_path} =====')# 创建VideoCapture对象cap = cv2.VideoCapture(path)# 检查是否成功打开视频if not cap.isOpened():print("Error opening video file")returnframe_rate = cap.get(cv2.CAP_PROP_FPS)total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))  # 获取视频的总帧数frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))  # 获取视频的宽度frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))  # 获取视频的高度print("原视频帧率=", frame_rate, "fps")print("原视频帧数=", total_frames)print("原视频尺寸=", frame_width, "x", frame_height)if frame_rate != fps:cap.set(cv2.CAP_PROP_FPS, fps)frame_rate = fps# 创建VideoWriter对象fourcc = cv2.VideoWriter_fourcc(*'mp4v') out = cv2.VideoWriter(out_path, fourcc, fps, (512, 512))frame_count = 0# 创建一个tqdm进度条pbar = tqdm(total=total_frames, ncols=70, unit='frame')while cap.isOpened():ret, frame = cap.read()if ret:if contains_face(frame) and frame_count % (frame_rate // fps) == 0:frame = crop_center(frame, 512, 512)out.write(frame)frame_count += 1pbar.update(1)  # 更新进度条else:breakpbar.close()  # 关闭进度条cap.release()out.release()
# 你的代码中存在一些可能影响最终视频与音频同步的潜在问题:# 当你使用cap.set(cv2.CAP_PROP_FPS, fps)尝试改变视频的帧率,这实际上并不会改变视频的内部帧率属性。CAP_PROP_FPS是一个读取属性,而不是写入属性。因此,你不能依靠这种方法来更改视频的帧率。
# 当你基于frame_rate // fps的模运算来决定是否抽取帧时,这假定了frame_rate可以被fps整除。如果frame_rate和fps不是整数倍的关系,那么视频的总时长可能会与原视频不完全匹配,这可能导致音频和视频的轻微不同步。
# 为了避免这些问题,你应该:# 不尝试设置CAP_PROP_FPS,而是通过抽取帧来实现目标帧率。
# 计算每个帧应该抽取的时间戳,确保与原始视频的帧持续时间一致。
# def process_video(path, out_path, target_fps=25):
#     print(f'[INFO] ===== process video from {path} to {out_path} =====')#     # 创建VideoCapture对象
#     cap = cv2.VideoCapture(path)#     # 检查是否成功打开视频
#     if not cap.isOpened():
#         print("Error opening video file")
#         return#     original_fps = cap.get(cv2.CAP_PROP_FPS)
#     total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
#     frame_duration = 1 / original_fps  # 原始视频每帧的持续时间#     # 创建VideoWriter对象
#     fourcc = cv2.VideoWriter_fourcc(*'mp4v') 
#     out = cv2.VideoWriter(out_path, fourcc, target_fps, (512, 512))#     frame_count = 0
#     target_frame_time = 0  # 目标帧的累积时间#     # 创建一个tqdm进度条
#     pbar = tqdm(total=total_frames, ncols=70, unit='frame')#     while cap.isOpened():
#         ret, frame = cap.read()
#         if ret:
#             current_time = cap.get(cv2.CAP_PROP_POS_MSEC) / 1000  # 当前帧的时间戳(秒)#             # 如果当前时间等于或超过目标帧时间,则写入帧
#             if current_time >= target_frame_time:
#                 if contains_face(frame):
#                     frame = crop_center(frame, 512, 512)
#                     out.write(frame)
#                 target_frame_time += frame_duration * (original_fps / target_fps)  # 下一帧的目标时间#             frame_count += 1
#             pbar.update(1)  # 更新进度条
#         else:
#             break#     pbar.close()  # 关闭进度条#     cap.release()
#     out.release()print(f'[INFO] ===== processed video =====')# 打开处理后的视频,获取总帧数、帧率和视频尺寸cap_out = cv2.VideoCapture(out_path)total_frames_out = int(cap_out.get(cv2.CAP_PROP_FRAME_COUNT))frame_rate_out = cap_out.get(cv2.CAP_PROP_FPS)frame_width = int(cap_out.get(cv2.CAP_PROP_FRAME_WIDTH))frame_height = int(cap_out.get(cv2.CAP_PROP_FRAME_HEIGHT))print(f'处理后的视频帧率: {frame_rate_out} fps')print(f'处理后的视频帧数: {total_frames_out}')print(f'处理后的视频尺寸: {frame_width}x{frame_height}')cap_out.release()def process_video_with_audio(input_path, output_path):audio_path = output_path.replace('.mp4', '_audio.aac')output_with_audio_path = output_path.replace('.mp4', '_with_audio.mp4')extract_audio(input_path, audio_path)process_video(input_path, output_path)merge_video_audio(output_path, audio_path, output_with_audio_path)# 删除临时文件os.remove(output_path)os.remove(audio_path)return output_with_audio_pathif __name__ == "__main__":for i in tqdm(range(1, 75), desc="Processing videos"):input_path = f"data/{i}/{i}.mp4"output_path = f"data/{i}/{i}_fc.mp4"if not os.path.isfile(input_path):print(f"文件 {input_path} 不存在.")continuefinal_output_path = process_video_with_audio(input_path, output_path)print(f"处理后的视频已保存至 {final_output_path}")

通过调整帧率和裁剪视频来处理视频,同时保留音频并保持音频和视频的同步。为了确保音频和视频的同步,关键点在于保持视频帧的持续时间和原始视频一致。当减少帧率时,重要的是要确保抽取的帧在时间上均匀分布,这样每个帧代表的时间间隔与原始视频相同,从而保持音频的同步。

在代码中,通过以下方式实现了这一点:

使用cv2.CAP_PROP_FPS属性读取原始视频的帧率。 设置目标帧率fps(例如25fps)。 在循环中,只写入那些在时间上符合目标帧率的帧。你通过frame_count % (frame_rate // fps) == 0这一条件实现,这确保了只有在正确的时间间隔下才抽取一帧。 然而,你的代码中存在一些可能影响最终视频与音频同步的潜在问题:

当使用cap.set(cv2.CAP_PROP_FPS, fps)尝试改变视频的帧率,这实际上并不会改变视频的内部帧率属性。CAP_PROP_FPS是一个读取属性,而不是写入属性。因此,你不能依靠这种方法来更改视频的帧率。 当你基于frame_rate // fps的模运算来决定是否抽取帧时,这假定了frame_rate可以被fps整除。如果frame_rate和fps不是整数倍的关系,那么视频的总时长可能会与原视频不完全匹配,这可能导致音频和视频的轻微不同步。 为了避免这些问题,你应该:

不尝试设置CAP_PROP_FPS,而是通过抽取帧来实现目标帧率。 计算每个帧应该抽取的时间戳,确保与原始视频的帧持续时间一致。

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

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

相关文章

WebSocket实现群聊功能、房间隔离

引用WebSocket相关依赖 <dependency><groupId>javax.websocket</groupId><artifactId>javax.websocket-api</artifactId><version>1.1</version></dependency><dependency><groupId>org.springframework</grou…

kafka入坑

快速入门 使用 Strimzi 项目时&#xff0c;在 Kubernetes 上启动和运行 Apache Kafka 集群非常简单&#xff01; Kubernetes Kind 是一个 Kubernetes 集群&#xff0c;以单个 Docker 镜像的形式实现&#xff0c;并以容器的形式运行。它主要用于测试 Kubernetes 本身&#xff…

mac电脑pdf合并,macpdf合并成一个pdf

在数字化办公和学习的今天&#xff0c;pdf文件因其跨平台兼容性强、格式稳定而成为了最受欢迎的文档格式之一。但随之而来的问题也接踵而至&#xff0c;如何将多个pdf文件合并为一个&#xff1f;这不仅关系到文档的整洁性&#xff0c;更是时间管理的重要环节。今天&#xff0c;…

股指期货如何交易?有哪些交易策略和操作技巧?

股指期货交易提供了多种策略和技巧&#xff0c;以适应不同的市场情况和投资者需求。以下是对股指期货交易的一些基本策略和操作技巧的介绍。 1.卖出股指期货套期保值 对于那些已经持有或预计将持有股票的投资者&#xff0c;如果对未来市场走势不确定或预期市场将下跌&#xf…

PostgreSQL安装/卸载(CentOS、Windows)

说明&#xff1a;PostgreSQL与MySQL一样&#xff0c;是一款开源免费的数据库技术&#xff0c;官方口号&#xff1a;The World’s Most Advanced Open Source Relational Database.&#xff08;世界上最先进的开源关系数据库&#xff09;&#xff0c;本文介绍如何在Windows、Cen…

windows下pip修改镜像地址

不修改镜像地址安装时候就会很慢 永久修改 pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/ 清华大学源&#xff1a;https://pypi.tuna.tsinghua.edu.cn/simple/ 豆瓣源 &#xff1a;http://pypi.douban.com/simple/ 腾讯源&#xff1a;http://mir…

工程实践1 项目:小超市商品管理系统

#include<stdio.h> #include<stdlib.h>typedef struct item {int num;//编号char name[10];//名字int cost;//进价&#xff08;成本&#xff09;int price;//售价int initial_quantity;//进货量&#xff08;初始量&#xff09;int sale_quantity;//销售量int waste…

【C++ Primer Plus】学习笔记 2

文章目录 前言一、简单变量1. 变量名2. 整型2.1 整型类型2.2 无符号类型2.3 char 类型2.4 signed char 和unsigned char2.5 bool类型 3.浮点数4.类型转换 总结 前言 该系列文章请点击专栏查看 一、简单变量 1. 变量名 C提倡使用有一定含义的变量名&#xff0c;必须遵循几种简…

PyCharm: Python 开发者的首选 IDE

PyCharm 是由 JetBrains 公司开发的一款专为 Python 语言设计的集成开发环境&#xff08;IDE&#xff09;。它以其强大的功能、高效的代码编辑、智能的代码分析和便捷的项目导航而受到全球开发者的青睐。本文将介绍 PyCharm 的核心特性、使用技巧以及如何充分利用 PyCharm 提升…

moment()获取时间

moment 是一个 JavaScript 日期处理类库。 使用&#xff1a; //安装 moment npm install moment -- save 引用 //在main.js中全局引入 import moment from "moment" 设定moment区域为中国 //import 方式 import moment/locale/zh-cn moment.locale(zh-cn); …

ai绘画软件哪个好用?这5个工具值得尝试

这段时间云南上亿只蝴蝶翩翩起舞&#xff0c;仿佛大自然最绚烂的画布&#xff0c;不禁让人思考&#xff0c;若能将这份灵动与色彩完美捕捉于画布之上&#xff0c;该是多么奇妙的事。 幸运的是&#xff0c;现在无需远行&#xff0c;无需等待&#xff0c;只需一些创意&#xff0…

python 基础语法整理

注释声明命名规范数据类型简单数据类型复合数据类型 打印输出类型转换随机数获取布尔类型流程控制语句循环语句字符串操作拼接替换分割与连接大小写转换空白字符删除 切片列表操作访问/赋值判断是否存在元素添加/删除复制排序 元组集合字典空集合与空字典 函数声明多返回值函数…

【笔记-MyBatis】StatementHandler

Author&#xff1a;赵志乾 Date&#xff1a;2024-07-15 Declaration&#xff1a;All Right Reserved&#xff01;&#xff01;&#xff01; 1. 简介 StatementHandler封装了对JDBC各类Statement的操作&#xff0c;如设置fetchSize属性、设置查询超时时间、与数据库进行交互等&…

【TFTP工具(Trivial File Transfer Protocol)】

TFTP工具(Trivial File Transfer Protocol)使用&#xff1a; 一、概述 分为服务端和客户端&#xff0c;想要通信&#xff0c;一个配成服务端另一个配成客户端。TFTP 用于 UDP 端口号 69 其文件传输活动 要想使用TFTP需要的步骤&#xff1a; ① 本地安装客户端工具 ② 服务器…

【JS红宝书学习笔记】第25章 客户端存储

第25章 客户端存储 Cookie HTTP是无状态的&#xff0c;也就是说&#xff0c;你这次访问服务器&#xff0c;关闭后再次访问服务器&#xff0c;服务器是意识不到又是你来访问的。 登录时&#xff0c;浏览器需要帮我们在每一次请求里加入用户名和密码&#xff0c;这样才能做到保…

Supervised Contrastive Learning

paperhttps://arxiv.org/abs/2004.11362githubhttps://github.com/HobbitLong/SupContrast个人博客位置http://myhz0606.com/article/SupCon 1 Motivation 经典的自监督对比学习方法以instance discrimination作为pretext task。在这种方法中&#xff0c;会对batch的图片进行…

【书生大模型实战】L0-Git 基础知识

一、关卡任务 任务1: 破冰活动&#xff1a;自我介绍任务2: 实践项目&#xff1a;构建个人项目 二、实验过程 2.1 破冰行动 每位参与者提交一份自我介绍。 提交地址&#xff1a;GitHub - InternLM/Tutorial: LLM Tutorial 的 camp3 分支&#xff5e; 要求&#xff1a; 命名…

鸿蒙开发工程师面试-架构篇

1. 假如让你负责鸿蒙App架构设计&#xff0c;你会关注哪些方面&#xff1f; 分层架构设计&#xff1a; 将应用划分为产品定制层、基础特性层和公共能力层&#xff0c;以降低层间依赖性&#xff0c;提升代码可维护性。通过分层架构设计&#xff0c;进一步明确每层的职责和层间交…

R-CNN、Fast R-CNN和Faster R-CNN:目标检测的进化之路

在计算机视觉的世界里,目标检测是一个重要的任务,它的目标是找到图像中的特定物体,并标注出它们的位置。这项技术广泛应用于自动驾驶、安防监控等领域。为了让计算机能够准确高效地完成这一任务,科学家们提出了许多优秀的算法,其中最具代表性的就是R-CNN、Fast R-CNN和Fas…

Linux驱动开发-04LED灯驱动实验(直接操作寄存器)

一、Linux 下LED 灯驱动原理 Linux 下的任何外设驱动&#xff0c;最终都是要配置相应的硬件寄存器。驱动访问底层的硬件除了使用内存映射将物理地址空间转化为虚拟地址空间&#xff0c;去进行读写修改&#xff0c;还可以通过各种子系统函数去进行操作 1.1 地址映射 MMU 全称…