【目标检测】视频输出体积太大?分析视频的编码与码率问题

在做视频目标检测时,发现一个问题,检测输出完的视频时大时小,有时输出体积过大,造成播放器播放时严重卡顿现象。本文就这一情况进行分析,并就该问题提出相关解决方案。

视频基础知识

隔行扫描和逐行扫描

早期电视台在传输节目信息时,由于带宽有限,于是想在带宽不变的情况下,增加图像的分辨率,让画面看起来更清晰,于是就采用隔行扫描的方式,如下图所示[1],第一帧扫描奇数行的数据,第二帧扫描偶数行的数据,交替进行。由于视觉暂留,在人眼看来就是完整的视频图像。

在这里插入图片描述
隔行扫描1920x1080分辨率的视频也简称1080i,逐行扫描则称为1080p。

现在的带宽已经能满足绝大多数逐行扫描的视频,因此隔行扫描逐渐被淘汰,后文所提视频也均是逐行扫描视频。

视频分辨率

视频分辨率指的是每一帧画面有多少像素点,目前广泛采用的标准有720p、1080p、2K、4K。比如,2K分辨率的长边大于2000,就可称2k分辨率。下表是电视标准的分辨率标准[1],与手机之类的2k、4K分辨率数值不一定相同。
在这里插入图片描述

视频帧率

帧率很简单,即一秒钟播放多少帧画面,比如30FPS表示一秒钟播放30帧画面。

但在很多机器上,比如大疆的机器上,设置30FPS之后,实际拍摄的视频却是29.97帧;设置60FPS之后,实际拍摄的视频是59.94帧。

这个现象是由于NTSC彩色电视标准制定时,由于声音信息和电视信号过于接近,容易产生干扰,因此,把电视信号的帧率减小千分之一,导致这一情况出现[2]。

在这里插入图片描述

视频格式

在使用不同的摄像录制视频时,会有不同的格式,比较常见的是MP4、MOV、AVI等格式,这些格式被称作封装格式,相当于视频的一个大容器。这些格式多数可以相互转换,对于视频本身起决定作用的是视频的编码格式。

视频编码本质是对视频的压缩,如果视频不进行压缩,所需要的存储量是极其恐怖的,以1080P格式视频为例:

一帧画面包含像素点=1920x1080=2,073,600个像素点;
每个像素包含RGB三个通道,用3个字节(byte)存储;
那么一帧画面所需要的存储体积=2,073,600*3/1024/1024≈5.7M

因此,对视频编码十分必要,下面是常见封装格式的视频编码类型[3]:

在这里插入图片描述

视频压缩

上述这些视频编码都是通过压缩视频的画面帧来减小视频的体积,视频压缩包括帧内压缩和帧间压缩。

  • 帧内压缩

帧内压缩就是对单帧图像进行压缩,以JPEG压缩方法为例[3],人眼对亮度比较敏感,对颜色不太敏感,因此算法尽可能保留明度信息,而压缩色度信息。

在这里插入图片描述

  • 帧间压缩

帧间压缩是利用连续帧的时序信息,对视频进一步压缩。以H.264视频编码为例[3],它将视频分成I帧,P帧和B帧。I帧即通过帧内压缩得到的压缩视频帧,P帧是利用相邻I帧之间的运动变化关系,预测得到;B帧是利用相邻P帧进一步双向预测得到。

在这里插入图片描述
通过这样两步操作,让视频的体积大大减小。

视频码率

虽然上述视频编码方式能够极大压缩视频体积,不过影响视频质量关键因素还包括码率。如果采用固定码率进行编码,如果视频太过复杂,比如很多随机粒子,就会让视频看起来非常模糊。

视频码率又称比特率(bitrate),表示视频每秒所包含的数据量。常见的码率可分为固定码率(CBR)/可变码率(VBR)/固定质量(CRF)/平均码率(ABR)/固定量化参数(CQP)等。

固定码率即码率恒定,优点是码率可控,缺点是简单场景码率冗余,复杂场景码率不够用,因此用的不多。

可变码率是指码率按需进行分配,简单场景码率低,复杂场景码率高,用的最多,在PR中,还提供了VBR2次编码的选项,即包含一个目标码率和一个最大码率,因此VBR被广泛使用。

在这里插入图片描述

OpenCV视频编码

了解完上述基础知识后,不难发现,在视频分辨率和帧率固定的基础上,视频体积的大小主要取决于视频的编码格式和码率。

在OpenCV中,通过cv2.VideoWriter_fourcc来定义视频编码,例如*'mp4v'是采用MPEG-4的编码形式:

vid_writer[i] = cv2.VideoWriter(save_path, cv2.VideoWriter_fourcc(*'mp4v'), fps, (w, h))

此外,它还支持以下编码格式:

H.264 / AVC:

  • H264
  • X264
  • AVC1

H.265 / HEVC:

  • HEVC
  • H265
  • X265

MPEG-4:

  • MP4V
  • DIVX

Motion JPEG:

  • MJPG

MPEG-1:

  • MPG1

MPEG-2:

  • MPG2

XVID:

  • XVID

WMV:

  • WMV1
  • WMV2

视频码率修改

虽然OpenCV可以自定义编码方式,但无法直接修改码率,这导致有些视频输出之后,码率变得极大,比如这段12秒中的1080p视频,码率达到71150kps,整个文件110M大小。

在这里插入图片描述
在Python,可以通过两种方式去修改视频码率。

第一种方式是通过调用FFmpeg的方式,示例:

import subprocess# 输入和输出视频文件路径
input_video = 'input.mp4'
output_video = 'output.mp4'# 设置比特率(这里设置为1000k)
bitrate = '1000k'# 构建 FFmpeg 命令
ffmpeg_command = f'ffmpeg -i {input_video} -b:v {bitrate} {output_video}'# 运行 FFmpeg 命令
try:subprocess.run(ffmpeg_command, shell=True, check=True)print("视频重新编码成功!")
except subprocess.CalledProcessError as e:print(f"视频重新编码失败: {e}")

不过该方式需要提前下载安装FFmpeg方式,并不是很便利。

第二种方式是直接调用moviepy库,底层也是使用FFmpeg,不过无需下载安装:
示例:

import os
from moviepy.editor import VideoFileClip# 指定视频文件所在文件夹路径
videos_directory = "cs1/"
videos_save = "cs2"# 设置目标比特率(kbps)
target_bitrate = "20208k"  # 例如,设置为 20208 kbps# 遍历指定文件夹中的所有视频文件
for file in os.listdir(videos_directory):if file.endswith(".mp4") or file.endswith(".avi") or file.endswith(".mov"):# 构建视频文件的完整路径file_path = os.path.join(videos_directory, file)# 读取视频文件clip = VideoFileClip(file_path)# 写入视频文件并设置比特率output_file = os.path.join(videos_save, file)clip.write_videofile(output_file, codec='libx264', bitrate=target_bitrate)print(f"视频 {file} 处理完成并写入 {output_file}")print("批量处理完成")

由于视频编码默认采用的是VBR,因此尽管这里设置了目标码率为20208kbps,实际输出码率为21187kps,会接近目标码率,但并非固定。

在这里插入图片描述
通过这样处理之后,视频本身的观感影响不大,但体积减小了2/3。

更进一步,可以将修改码率的操作和保存视频的流程结合起来,下面是解决实际需求,需要对视频裁剪的同时,根据原视频的码率修改输出的视频。

下面的代码是保存多个文件,尝试过对单帧处理时直接修改码率,不过会出问题,因为码率需要考虑视频连续帧的情况,因此只能全部做完上一步,再统一处理码率问题。

import cv2
from moviepy.editor import VideoFileClipdef get_original_bitrate(input_video):cap = cv2.VideoCapture(input_video)if not cap.isOpened():print("无法打开视频文件")return None# 获取视频的原始比特率original_bitrate = cap.get(cv2.CAP_PROP_BITRATE)# 释放资源cap.release()return original_bitratedef crop_video(input_video, output_video, target_bitrate):# 对视频进行空间上的裁剪(使用 OpenCV)cap = cv2.VideoCapture(input_video)if not cap.isOpened():print("无法打开视频文件")return# 获取视频的基本信息fps = cap.get(cv2.CAP_PROP_FPS)frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))# 设置输出视频的编解码器和写入对象fourcc = cv2.VideoWriter_fourcc(*'mp4v')out = cv2.VideoWriter(output_video, fourcc, fps, (894, 710))while True:ret, frame = cap.read()if not ret:break# 对每一帧进行裁剪cropped_frame = frame[161:871, 493:1387]  # 这里是你想要的空间裁剪区域的坐标# 写入裁剪后的帧到输出视频文件out.write(cropped_frame)# 释放资源cap.release()out.release()cv2.destroyAllWindows()# 读取视频文件clip = VideoFileClip(output_video)output_video2 = output_video.replace('.mp4', '_Update.mp4')# 保存裁剪和修改比特率后的视频clip.write_videofile(output_video2, codec='libx264', bitrate=target_bitrate)if __name__ == '__main__':# 输入视频文件路径input_video_path = 'Video.mp4'# 输出视频文件路径output_video_path = input_video_path.replace('.mp4', '_Crop.mp4')# 获取视频的原始比特率original_bitrate = get_original_bitrate(input_video_path)# 设置目标比特率original_bitrate = str(int(original_bitrate)) + 'k'# 调用函数进行视频裁剪和修改比特率crop_video(input_video_path, output_video_path, original_bitrate)

视频推荐编码参考

码率越低,视频体积越小。然而,当码率过低时,会影响到视频本身的清晰度。

下表是两大主流视频平台的推荐码率,低于该码率可能会影响视频质量,高出太多则会触发平台二次压缩,对视频创作者来说,具有参考价值。

在这里插入图片描述

在这里插入图片描述

参考

[1] 你知道什么是逐行扫描与隔行扫描吗?https://www.bilibili.com/video/BV1Xu411B7x8/
[2] 影视飓风将停止制作25帧视频 https://www.bilibili.com/video/BV1hp4y1f7B5/
[3] 【科普】“视频”是怎么来的?H.264、码率这些词又是什么意思? https://www.bilibili.com/video/BV1nt411Q7S6

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

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

相关文章

恒创:多链路负载均衡是什么意思

多链路负载均衡是一种网络架构技术,它通过将流量分散到多个网络链路上,以提高网络的性能和可靠性。这种技术可以应用于各种场景,如数据中心、云计算、企业网络等。 在多链路负载均衡中,流量被分配到多个网络链路上,以…

【深度学习目标检测】十、基于yolov5的火灾烟雾识别(python,目标检测)

YOLOv5是目标检测领域一种非常优秀的模型,其具有以下几个优势: 1. 高精度:YOLOv5相比于其前身YOLOv4,在目标检测精度上有了显著的提升。YOLOv5使用了一系列的改进,如更深的网络结构、更多的特征层和更高分辨率的输入图…

物联网对接使用蓝牙还是WiFi,应该如何选择?

蓝牙是一种无线技术协议,可促进连接设备之间短距离的数据交换。它依赖于物理邻近性并使用2.400至2.485 GHz之间的UHF(超高频)无线电波。蓝牙旨在创建个人区域网络(PAN)并在笔记本电脑、智能手机和外围设备等计算设备之…

Unity SRP 管线【第四讲:URP 阴影】

URP 全文源码解析参照 引入 在UniversalRenderer.cs/ line 505行处 此处已经准备好了所有渲染数据(所有数据全部存储在了renderingData中) 我们只用renderingData中的数据初设置mainLightShadows bool mainLightShadows m_MainLightShadowCasterPass…

【MAC】M2 安装mysql

一、docker下载地址 下载地址 二、安装docker完成 三、安装mysql 一、拉取镜像 # 拉取镜像 docker pull mysql# 或者 docker pull mysql:latest# 以上两个命令是一致的,默认拉取的就是 latest 版本的# 我们还可以用下面的命令来查看可用版本: docker…

Docker介绍,Docker安装

docker镜像仓库官网 一、Docker的基本概念 1.Docker的三大核心组件 docker 镜像 --------docker images docker 仓库---------docker registeries docker 容器---------docker containers 2.Docker 镜像 Docker镜像是运行docker容器时的只读模板,每一个镜像由一…

【Transformer】Transformer and BERT(1)

文章目录 TransformerBERT 太…完整了!同济大佬唐宇迪博士终于把【Transformer】入门到精通全套课程分享出来了,最新前沿方向 学习笔记 Transformer 无法并行,层数比较少 词向量生成之后,不会变,没有结合语境信息的情…

数据加密标准DES硬件实现(Modelsim)

数据加密标准DES硬件实现 本文内容摘要理论依据和设计内容仿真结果整体代码 本文内容摘要 本文设计并验证了DES的密钥扩展通路,分别采用Round Based方法和Pipeline方法两种方式设计并验证DES的明文通路 理论依据和设计内容 首先,要了解分组密码算法及DE…

cdr格式怎么打开?cdr文件查看工具CDR Viewer功能介绍

CDRViewer Pro for Mac是一款专业的矢量图形文件查看器,主要用于打开、浏览和查看CorelDRAW(CDR)文件。以下是该软件的主要功能和特点: CDR文件支持:CDRViewer Pro可以快速加载和显示CorelDRAW(CDR&#x…

【面试】Java最新面试题资深开发-微服务篇(1)

问题九:微服务 什么是微服务架构?它与单体架构相比有哪些优势和劣势?解释一下服务发现和服务注册是什么,它们在微服务中的作用是什么?什么是API网关(API Gateway)?在微服务中它有何…

大模型(LLM)+词槽(slot)构建动态场景多轮对话系统

构建动态场景多轮对话系统 引言 在人工智能和自然语言处理领域,聊天机器人的开发一直是一个热点话题。近年来,随着大型语言模型(LLM)的进步,构建能够理解和响应各种用户需求的聊天机器人变得更加可行和强大。本文将介…

Acrel-1000DP分布式光伏系统在某重工企业18MW分布式光伏中应用——安科瑞 顾烊宇

摘 要:分布式光伏发电特指在用户场地附近建设,运行方式以用户侧自发自用、余电上网,且在配电系统平衡调节为特征的光伏发电设施,是一种新型的、具有广阔发展前景的发电和能源综合利用方式,它倡导就近发电,就…

DiffUtil + RecyclerView 在 Kotlin中的使用

很惭愧, 做了多年的Android开发还没有使用过DiffUtil这样解放双手的工具。 文章目录 1 DiffUtil 用来解决什么问题?2 DiffUtil 是什么?3 DiffUtil的使用4 参考文章 1 DiffUtil 用来解决什么问题? 先举几个实际开发中的例子帮助我们感受下: 加载内容流时,第一次加载了ABC,…

gitlab(gitlab-ce)下载,离线安装

目录 1.下载 2.安装 3.配置 4.启动 5.登录 参考: 1.下载 根据服务器操作系统版本,下载对应的RPM包。 gitlab官网: The DevSecOps Platform | GitLab rpm包官网下载地址: gitlab/gitlab-ce - Results in gitlab/gitlab-ce 国内镜像地…

JVM-4-垃圾收集基础

引用计数算法 在对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加一;当引用失效时,计数器值就减一;任何时刻计数器为零的对象就是不可能再被使用的。 对象objA和objB都有字段instance,赋值…

分布式链路追踪 —— 基于Dubbo的traceId追踪传递

文章目录 原文链接RpcContext 上下文对象Dubbo 过滤器(Filter)对象基于Dubbo的traceId追踪传递实现 原文链接 RpcContext 上下文对象 在实现 Dubbo 调用之间的链路跟踪之前,先简单了解 RpcContext 上下文对象和 Filter 过滤器对象&#xff…

python排序算法,冒泡排序和快排

对于排序算法中比较知名的两个算法,分别就是冒泡排序和快速排序,在日常学习和使用中都会听到这两种排序算法的名称,这里主要介绍如何使用python来实现这两种排序算法。 冒泡排序的实现:一是从集合第一个元素开始,每两…

单片机计数功能

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、计数器是什么?1.1 应用 二、计数器原理框图及对输入信号的要求2.1 原理框图2.2对输入信号的要求 三、使用步骤3.1 配置为计数模式3.2 装初值3.3…

0基础学习VR全景平台篇第129篇:认识单反相机和鱼眼镜头

上课!全体起立~ 大家好,欢迎观看蛙色官方系列全景摄影课程! 一、相机 单反和微单 这里说的相机是指可更换镜头的单反/微单数码相机。那两者有何差异呢? 1)取景结构差异 两者最直观的区别在于,微单相机…

html中RGB和RGBA颜色表示法

文章目录 RGB什么是RGBRGB颜色模式的取值范围RGB常用颜色对照表 RGBA什么是RGBARGBA颜色模式的取值范围 总结 RGB 什么是RGB RGB是一种颜色空间,其中R代表红色(Red)、G代表绿色(Green)、B代表蓝色(Blue&a…