FFmpeg基础: YUV像素格式介绍和使用

news2024/11/26 5:25:46

文章目录

    • YUV像素格式
    • YUV采样
    • YUV格式分类
    • YUV存储模式
    • FFmpeg读取YUV数据
    • YUV和RGB转换

YUV像素格式

在图片中我们一般都是通过RGB(红-绿-蓝)格式来表示一个像素点。而在视频当中为了兼容黑白和彩色视频我们通过YUV来表示一个像素点,YUV中Y表示像素点的灰度(也就是亮度分量),而UV表示色度分量,U称为蓝色投影也就是像素蓝色部分去掉亮度Y之后的值,V称为红色投影也就是像素红色部分去掉亮度Y的值。

如果只有Y亮度分量,没有UV颜色分量,那么图像就会变成黑白色的图像,由于YUV像素的这种特点,YUV像素格式能同时兼容彩色图像和黑白图像。

YUV采样

和RGB像素格式不同,由于人的眼睛对亮度Y敏感,而对颜色分量UV不敏感,所以我们可以在保证图像效果的同时降低色度分量的采样数据,从而实现对画面数据的压缩。目前流行的YUV采样,基本都是降低色度分量的采集。在所有的YUV格式中,UV的采样数据都是相等的,只是在有的YUV格式中需要Y分量之间共享UV分量。

YUV格式分类

YUV4:4:4
YUV4:4:4格式中每个像素点进行YUV全采样。由于每个分量存储占用一个字节,YUV每个像素深度是24位,也就是3个字节,这和RGB占用空间是相同的。

YUV4:2:2
YUV4:2:2水平方向Y分量与UV分量2:1采样,垂直方向不降低采样率。YUV4:2:2一个像素深度是:1x8 + 0.5x8 + 0.5x8 = 16位,也就是占用2个字节。

YUV4:2:0
YUV4:2:0垂直方向和水平方向上Y分量和UV分量的采样比都是2:1。YUV4:2:0一个像素深度是1x8 + 0.5x8 = 12位,也就是占用1.5个字节。

三种像素格式之间的对比图如下图所示:
在这里插入图片描述

YUV存储模式

YUV存储模式分为打包模式和平面模式,在打包模式中,YUV分量存储在单个数组中,YUV分量是顺序交错存储。在平面模式中,YUV分量存储在三个不同的平面数组中。

YUV4:4:4的打包存储模式如下图所示:
在这里插入图片描述

YUV4:2:2采样格式有两种存储方式分别为YUY2和UYVY。YUV2和UYVY两种数据格式基本相同,都是两个Y分量共用一套UV,不同的是字节顺序发生了颠倒。

两种打包存储格式如下图所示:
在这里插入图片描述

YUV4:2:0都采用了平面存储模式,总共分为四种:IMC2、IMC4、YV12、NV12。所有的4:2:0模式中,色度分量无论是水平还是垂直方向上,采样数都是亮度的1/4.

IMC2
平面存储模式中都是先存储视频帧中所有的Y分量,Y分量存储完毕之后才开始存储色度分量。IMC2格式中,是先存储Y分量,然后再存储V分量、最后存储U分量。
存储UV分量的空间分别Y分量空间的1/4,YUV内存比例为4:1:1。

IMC4
IMC4和IMC2的存储模式相同,差异是IMC4中UV分量的存储顺序发生了颠倒。两种模式的存储对比图如下图所示:
在这里插入图片描述

YV12/YUV420P(I420)
YV12和IMC2及IMC4的存储方式不同,存储色度分量的内存步长是亮度分量的一半。同时YUV420P和YV12的UV存储顺序刚好相反。两种模式存储结构如下图所示:
在这里插入图片描述

NV12
NV12格式先存储Y分量平面,之后UV分量间隔存储,存储的空间结构如下图所示:
在这里插入图片描述

FFmpeg读取YUV数据

由于YUV不同格式的存储结构不同,在使用ffmpeg读取YUV数据的时候读取方式也有差异,这里就介绍一下常见格式的YUV数据的读取方式:

读取YUV420P数据

//分配图像内存
int buffer_size = av_image_get_buffer_size(AV_PIX_FMT_YUV420P,
    1920,
    1080,
    1);
uint8_t *out_buffer = (uint8_t *)av_malloc(buffer_size);
//读取YUV420P数据
AVFrame *frame = av_frame_alloc();
av_image_fill_arrays(frame->data,
    frame->linesize,
    out_buffer,
    AV_PIX_FMT_YUV420P,
    1920,
    1080,
    1);
frame->format = AV_PIX_FMT_YUV420P;
frame->width = 1920;
frame->height = 1080;

int width = 1920;
int height = 1080;

uint8_t * file_buffer = (uint8_t *)av_malloc(1920 * 1080 * 3 / 2);

FILE *in_file = fopen("input.yuv", "rb");
int pts = 0;
while (1) 
{
    //读取YUV420P数据
    if (fread(file_buffer, 1, width * height * 3 / 2, in_file) <= 0) 
    {
        break;
    }
    else if (feof(in_file)) 
    {
        break;
    }

    //封装yuv帧数据
    frame->data[0] = file_buffer;                         //Y起始数据索引
    frame->data[1] = file_buffer + width * height;        //U数据起始索引
    frame->data[2] = file_buffer + width * height * 5 / 4;//V起始数据索引
    frame->linesize[0] = width;    //Y数据的行宽
    frame->linesize[1] = width / 2;//U数据的行宽
    frame->linesize[2] = width / 2;//V数据的行宽
}

读取NV12数据

//分配图像内存
int buffer_size = av_image_get_buffer_size(AV_PIX_FMT_NV12,
    1920,
    1080,
    1);
uint8_t *out_buffer = (uint8_t *)av_malloc(buffer_size);
//读取NV12数据
AVFrame *frame = av_frame_alloc();
av_image_fill_arrays(frame->data,
    frame->linesize,
    out_buffer,
    AV_PIX_FMT_NV12,
    1920,
    1080,
    1);
frame->format = AV_PIX_FMT_NV12;
frame->width = 1920;
frame->height = 1080;

uint8_t * file_buffer = (uint8_t *)av_malloc(1920 * 1080 * 3 / 2);

FILE *in_file = fopen("input.nv12", "rb");
int pts = 0;
while (1) 
{
    //读取NV12的数据
    if (fread(file_buffer, 1, width * height * 3 / 2, in_file) <= 0) 
    {
        break;
    }
    else if (feof(in_file)) 
    {
        break;
    }

    frame->data[0] = file_buffer;      //Y的起始位置                
    frame->data[1] = file_buffer + 1920 * 1080; //UV的起始位置

    frame->linesize[0] = 1920;    //Y的行宽
    frame->linesize[1] = 1920;//UV的行宽
}

YUV和RGB转换

YUV转RGB

R = Y + 1.403(V - 128)
G = Y - 0.344(U - 128) - 0.714(V - 128)
B = Y + 1.770(U - 128)

RGB转YUV

Y = 0.2990R + 0.5870G + 0.1140B
U =0.1684R − 0.3316G + 0.5B + 128
V = 0.5R - 0.4187G - 0.0813B + 128

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

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

相关文章

【nowcoder】笔试强训Day6

目录 一、单选题 二、多选题 三、编程题 3.1不要二 3.2 把字符串转成整数 一、单选题 1.下面哪段程序能够正确的实现了GBK编码字节流到UTF-8编码字节流的转换&#xff1a; A dstString.frombytes(src,”GBK”).getbytes(“UTF-8”) B dstnew String (src,”GBK”).getb…

计算机视觉与图形学-神经渲染专题-非刚体NeRF

《Fast Non-Rigid Radiance Fields from Monocularized Data》链接&#xff1a;https://graphics.tu-bs.de/publications/kappel2022fast摘要单目动态场景下的 3D 重建和新颖视图合成最近受到越来越多的关注。现有工作在合成给定和前向拍摄的真实世界数据下可以合成较好的结果&…

iPhone如何恢复丢失/消失的通讯录联系人,试试这6 种恢复方案

“在我更新 iOS 后&#xff0c;数百个联系人从我的 iPhone 上消失了。我试图从 iCloud 恢复我的联系人存档。我所看到的只是“没有可用的档案”。请来人帮忙&#xff01;” 每当发布新的 iOS 版本时&#xff0c;许多 iPhone 用户都会争先恐后地开始更新。然而&#xff0c;他们…

【Python学习记录】matplotlib绘图基本配置

✨ 博客主页&#xff1a;小小马车夫的主页 ✨ 所属专栏&#xff1a;Python学习记录 文章目录前言1、设置颜色2、设置每个点marker3、设置标题、X轴、Y轴文字4、设置刻度5、同一图中画多条线、绘制图例6、设置图层顺序7、多个图的设置subplot8、保存图片总结前言 matplotlib是p…

python中文编码json中文输出问题

python2.x版本的字符编码有时让人很头疼&#xff0c;遇到问题&#xff0c;网上方法可以解决错误&#xff0c;但对原理还是一知半解&#xff0c;本文主要介绍 python 中字符串处理的原理&#xff0c;附带解决 json 文件输出时&#xff0c;显示中文而非 unicode 问题。首先简要介…

人机交互-广州DACAI触摸屏开发中遇到的一些(屏幕和编程)问题

目录 背景 一、屏幕相关 1、厂家给的指令集资料可能有错误&#xff0c;请以软件VisualTFT中的指令助手为准。 2、屏幕程序下载方式 3、SD卡文件格式问题 4、画面id的问题 巨坑&#xff01;&#xff01;&#xff01; 5、子画面变暗的问题 6、 VisualTFT自带的键盘问题 …

【openGauss】一键编译openGauss3.1+dolphin,体验新增的mysql兼容特性

前言 前两天写了一篇openGauss3.1关于mysql的相关特性&#xff0c;但由于openGauss官网提供下载的版本还是9月30号第一次发布的版本&#xff0c;很多特性都还没合入&#xff0c;所以不少爱好者不能轻易体验到。 虽然openGauss已经提供了“一键式编译脚本”,但是还是得做一些前…

Linux系统下的常用文件目录指令

文件目录指令 pwd (Print Working Directory):显示当前工作目录的绝对路泾 ls (list) 基本语法:ls[选项][目录或是文件]常用选项 -a:显示当前目录所有的文件和目录&#xff0c;包括隐藏的。 -l:以列表的方式显示信息 cd (change directory) :切换到指定目录 基本语法:cd参数理…

5G无线技术基础自学系列 | 5G网络速率问题分析

素材来源&#xff1a;《5G无线网络规划与优化》 一边学习一边整理内容&#xff0c;并与大家分享&#xff0c;侵权即删&#xff0c;谢谢支持&#xff01; 附上汇总贴&#xff1a;5G无线技术基础自学系列 | 汇总_COCOgsta的博客-CSDN博客 前面介绍了接入性和移动性两类问题的处…

node.js+uni计算机毕设项目湖南工商大学财务信息查询小程序(程序+小程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等…

计网第三章.数据链路层—封装成帧、差错检测

以下是湖科大计算机网络公开课的笔记 1 . 数据链路层概述 1.1 一些概念 链路&#xff08;Link&#xff09;就是从一个结点到相邻结点的一段物理线路&#xff0c;而中间没有任何其他的交换结点 数据链路&#xff08;Data Link&#xff09; 是指实现通信协议的硬件和软件加到…

【自然语言处理】最大熵马尔可夫模型

有任何的书写错误、排版错误、概念错误等&#xff0c;希望大家包含指正。 由于这部分的参考资料比较少&#xff0c;网上大部分资料重复且不完整&#xff0c;对于一些关键计算没有推导&#xff0c;所以这里我主要讨论几篇论文和讲义。但是这些论文和讲义之间也有些许差别&#…

算法CPP时间复杂度

观察数据生成器可以发现对于每次操作均有 。 考虑将这些三元组想象成空间直角坐标系中 为对顶点的长方体。 将操作分成两部分&#xff0c;一部分是对 轴同时操作的&#xff0c;可以一开始就用前缀 统计完&#xff0c;将长方体变 成一个底面为阶梯状的直棱柱。另一部分是对 或…

【网络工程】9、实操-万达酒店综合项目(三)

接上篇《8、实操-万达酒店综合项目&#xff08;三&#xff09;》 之前我们按照项目要求进行模拟拓扑的构建实操&#xff0c;完成了办公区部分的网络配置&#xff0c;本篇我们来继续完成其他区域的网络配置。 一、总体架构情况 按照之前项目需求的拓扑图&#xff1a; 我们已经…

爱了爱了,Spring Cloud Alibaba内部微服务架构笔记真的太牛了

现如今微服务架构十分流行&#xff0c;而采用微服务构建系统也会带来更清晰的业务划分和可扩展性。同时&#xff0c;支持微服务的技术栈也是多种多样的&#xff0c;本文主要讲述我们为什么选择Spring Cloud和它的技术概要。 为什么微服务架构需要Spring Cloud 简单来说&#x…

【C++初阶】list的模拟实现

文章目录list的介绍list的模拟实现成员变量Member functionsconstructordestructoroperatorIterators正向迭代器反向迭代器beginendrbeginrendModifierspush_frontpop_frontpush_backpop_backinserteraseclear完整版代码list.hreverse_iterator.htest.cpplist的介绍 list是STL…

Selenium自动化测试环境搭建及问题

一、前言 目标&#xff1a;环境搭建及测试 主要问题&#xff1a;浏览器闪退&#xff0c;路径不明确&#xff0c;语法弃用 二、环境搭建&#xff08;自带python3.9以上&#xff09; 2.1.1、下载谷歌浏览器驱动 https://registry.npmmirror.com/binary.html?pathchromedriver/&…

数据结构---A星寻路算法

A星寻路算法第一步第二步第三步第四步JAVA实现用于寻找有效路径的算法。定义俩个集合 OpenList&#xff1a;可到达的格子 CloseList&#xff1a;已到达的格子 每一个格子都具有F、G、H这3个属性 G&#xff1a;从起点走到当前格子的成本&#xff0c;也就是已经花费了多少步。H&a…

生产级部署 Python 脚本,崩溃可自启

今天介绍一个生产级的流程管理工具 PM2&#xff0c;通常我们说到 PM2 的时候&#xff0c;都是在说如何部署 Node.js 程序&#xff0c;但是实际上 PM2 很强大&#xff0c;不仅仅可以用来管理 Node.js&#xff0c;它还可以用来管理 Python、PHP、Ruby、perl 等等。 这里就以 Pyt…

看了下华为工资,我不加班了

周五快下班&#xff0c;我本来是想继续好好上班的。那时候是晚上8点左右&#xff0c;跟我一个华为的朋友聊天&#xff0c;聊完之后&#xff0c;我气得把电脑合上&#xff0c;拿上花了7万巨款买的车钥匙&#xff0c;头也不回的走到电梯口&#xff0c;按下了下楼的电梯按钮。-事情…