图文详解YUV420数据格式

2023-11-03

原文地址:http://www.cnblogs.com/azraelly/archive/2013/01/01/2841269.html

1. YUV简介

YUV定义:分为三个分量,“Y”表示明亮度(Luminance或Luma),也就是灰度值;而“U”和“V” 表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。

YUV格式:有两大类:planar和packed。
对于planar的YUV格式,先连续存储所有像素点的Y,紧接着存储所有像素点的U,随后是所有像素点的V。
对于packed的YUV格式,每个像素点的Y,U,V是连续交*存储的。

YUV存储:格式其实与其采样的方式密切相关,主流的采样方式有三种,YUV4:4:4,YUV4:2:2,YUV4:2:0,关于其详细原理,可以通过网 上其它文章了解,这里我想强调的是如何根据其采样格式来从码流中还原每个像素点的YUV值,因为只有正确地还原了每个像素点的YUV值,才能通过YUV与 RGB的转换公式提取出每个像素点的RGB值,然后显示出来。 

YUV特点:也是一种颜色编码方法,它将亮度信息(Y)与色彩信息(UV)分离,没有UV信息一样 可以显示完整的图像,只不过是黑白的,这样的设计很好地解决了彩色电视机与黑白电视的兼容问题。并且,YUV不像RGB那样要求三个独立的视频信号同时传 输,所以用YUV方式传送占用极少的频宽

 图:用三个图来直观地表示采集的方式吧,以黑点表示采样该像素点的Y分量,以空心圆圈表示采用该像素点的UV分量。

2.  存储方式

    下面我用图的形式给出常见的YUV码流的存储方式,并在存储方式后面附有取样每个像素点的YUV数据的方法,其中,Cb、Cr的含义等同于U、V。

(1) YUVY 格式 (属于YUV422)

YUYV为YUV422采样的存储格式中的一种,相邻的两个Y共用其相邻的两个Cb、Cr,分析,对于像素点Y'00、Y'01 而言,其Cb、Cr的值均为 Cb00、Cr00,其他的像素点的YUV取值依次类推。
 
(2) UYVY 格式 (属于YUV422)
UYVY格式也是YUV422采样的存储格式中的一种,只不过与YUYV不同的是UV的排列顺序不一样而已,还原其每个像素点的YUV值的方法与上面一样。
 
(3) YUV422P(属于YUV422)
YUV422P 也属于YUV422的一种,它是一种Plane模式,即平面模式,并不是将YUV数据交错存储,而是先存放所有的Y分量,然后存储所有的U(Cb)分量, 最后存储所有的V(Cr)分量,如上图所示。其每一个像素点的YUV值提取方法也是遵循YUV422格式的最基本提取方法,即两个Y共用一个UV。比如, 对于像素点Y'00、Y'01 而言,其Cb、Cr的值均为 Cb00、Cr00。
(4)YV12,YU12格式(属于YUV420)

YU12和YV12属于YUV420格 式,也是一种Plane模式,将Y、U、V分量分别打包,依次存储。其每一个像素点的YUV数据提取遵循YUV420格式的提取方式,即4个Y分量共用一 组UV。注意,上图中,Y'00、Y'01、Y'10、Y'11共用Cr00、Cb00,其他依次类推。

(5)NV12、NV21(属于YUV420)

NV12和NV21属于YUV420格式,是一种two-plane模式,即Y和UV分为两个Plane,但是UV(CbCr)为交错存储,而不是分为三个plane。其提取方式与上一种类似,即Y'00、Y'01、Y'10、Y'11共用Cr00、Cb00

YUV420 planar数据存储, 以720×488大小图象YUV420 planar为例,

其存储格式是: 共大小为(720×480×3>>1)字节,

分为三个部分: Y分量:       (720×480)个字节   U(Cb)分量:  (720×480>>2)个字节     V(Cr)分量:   (720×480>>2)个字节

三个部分内部均是行优先存储,三个部分之间是Y,U,V 顺序存储。

即YUV数据的0--720×480字节是Y分量值,    720×480--720×480×5/4字节是U分量    720×480×5/4 --720×480×3/2字节是V分量。

4 :2: 2 和4:2:0 转换:

最简单的方式:

YUV4:2:2 ---> YUV4:2:0  Y不变,将U和V信号值在行(垂直方向)在进行一次隔行抽样。 YUV4:2:0 ---> YUV4:2:2  Y不变,将U和V信号值的每一行分别拷贝一份形成连续两行数据。

在YUV420中,一个像素点对应一个Y,一个4X4的小方块对应一个U和V。对于所有 YUV420图像,它们的Y值排列是完全相同的,因为只有Y的图像就是灰度图像。YUV420sp与YUV420p的数据格式它们的UV排列在原理上是完 全不同的。420p它是先把U存放完后,再存放V,也就是说UV它们是连续的。而420sp它是UV、UV这样交替存放的。(见下图) 有了上面的理论,我就可以准确的计算出一个YUV420在内存中存放的大小。 width * hight =Y(总和) U = Y / 4   V = Y / 4

所以YUV420 数据在内存中的长度是 width * hight * 3 / 2,

 

假设一个分辨率为8X4的YUV图像,它们的格式如下图:

图:YUV420sp格式

 

图:YUV420p数据格式如下图

旋转90度的算法:

public static void rotateYUV240SP(byte[] src,byte[] des,int width,int height)
 {
  int wh = width * height;
  //旋转Y
  int k = 0;
  for(int i=0;i<width;i++) {
   for(int j=0;j<height;j++)
   {
               des[k] = src[width*j + i];   
         k++;
   }
  }
  for(int i=0;i<width;i+=2) {
   for(int j=0;j<height/2;j++)
   { 
               des[k] = src[wh+ width*j + i]; 
               des[k+1]=src[wh + width*j + i+1];
         k+=2;
   }
  }
 }

YV12和I420的区别        

一般来说,直接采集到的视频数据是RGB24的格式,RGB24一帧的大小size=width×heigth×3 Bit,RGB32的size=width×heigth×4,如果是I420(即YUV标准格式4:2:0)的数据量是 size=width×heigth×1.5 Bit。       在采集到RGB24数据后,需要对这个格式的数据进行第一次压缩。即将图像的颜色空间由RGB2YUV。因为,X264在进行编码的时候需要标准的 YUV(4:2:0)。但是这里需要注意的是,虽然YV12也是(4:2:0),但是YV12和I420的却是不同的,在存储空间上面有些区别。如下:
经过第一次数据压缩后RGB24->YUV(I420)。数据量将减少一半, RGB24->YUV(YV12)有很大损失。经过X264编码后,数据量将大大减少。将编码后的数据打包,通过RTP实时传送。到达目的地后,将数据取出,进行解码。完成解码后,数据仍然是YUV格式的,需要一次转换,这样windows的驱动才可以处理,就是YUV2RGB24。

YV12 : 亮度(行×列) + U(行×列/4) + V(行×列/4)
I420 : 亮度(行×列) + V(行×列/4) + U(行×列/4)
YUY2  是 4:2:2  [Y0 U0 Y1 V0]
yuv420p:yyyyyyyy uuuuuuuu vvvvv
yuv420: yuv yuv yuv

 

YUV420P,Y,U,V三个分量都是平面格式,分为I420和YV12。在I420格式(即:YUV);但YV12则是相反(即:YVU)。
YUV420SP, Y分量平面格式,UV打包格式, 即NV12。 NV12与NV21类似,U 和 V 交错排列,不同在于UV顺序。
I420: YYYYYYYY UU VV    =>YUV420P
YV12: YYYYYYYY VV UU    =>YUV420P
NV12: YYYYYYYY UVUV     =>YUV420SP
NV21: YYYYYYYY VUVU     =>YUV420SP

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

图文详解YUV420数据格式 的相关文章

  • 为什么相同的代码在同一台计算机上的执行时间可能不同?

    我是 C 编程新手 我编写了代码并希望获得它的运行时 这就是我所做的 每次运行代码时 我都会得到不同的运行时值 这样对吗 或者我的代码有问题吗 int main int argc char argv time t start end sta
  • 如何使用MemoryCache代替Timer来触发一个方法?

    以下方法通过等待已运行操作的结果来处理并发请求 对数据的请求可能会使用相同 不同的凭据同时出现 对于每组唯一的凭据 最多可以有一个GetCurrentInternal呼叫正在进行中 当准备就绪时 该呼叫的结果将返回给所有排队的服务员 pri
  • std::cout 和 std::wcout 有什么区别?

    在c 中 有什么区别std cout and std wcout 它们都控制流缓冲区的输出或将内容打印到控制台 或者它们只是相似吗 它们作用于不同的字符类型 std cout uses char作为字符类型 std wcout uses w
  • 如何在 C# 中从 UNIX 纪元时间转换并考虑夏令时?

    我有一个从 unix 纪元时间转换为 NET DateTime 值的函数 public static DateTime FromUnixEpochTime double unixTime DateTime d new DateTime 19
  • 如何为 C 分配的 numpy 数组注册析构函数?

    我想在 C C 中为 numpy 数组分配数字 并将它们作为 numpy 数组传递给 python 我可以做的PyArray SimpleNewFromData http docs scipy org doc numpy reference
  • ASP.NET:获取自 1970 年 1 月 1 日以来的毫秒数

    我有一个 ASP NET VB NET 日期 我试图获取自 1970 年 1 月 1 日以来的毫秒数 我尝试在 MSDN 中寻找方法 但找不到任何东西 有谁知道如何做到这一点 从 NET 4 6 开始 该方法ToUnixTimeMillis
  • 将 Excel 导入到 Datagridview

    我使用此代码打开 Excel 文件并将其保存在 DataGridView 中 string name Items string constr Provider Microsoft Jet OLEDB 4 0 Data Source Dial
  • 使用 JNI 从 Java 代码中检索 String 值的内存泄漏

    我使用 GetStringUTFChars 从使用 JNI 的 java 代码中检索字符串的值 并使用 ReleaseStringUTFChars 释放该字符串 当代码在 JRE 1 4 上运行时 不会出现内存泄漏 但如果相同的代码在 JR
  • C++:.bmp 到文件中的字节数组

    是的 我已经解决了与此相关的其他问题 但我发现它们没有太大帮助 他们提供了一些帮助 但我仍然有点困惑 所以这是我需要做的 我们有一个 132x65 的屏幕 我有一个 132x65 的 bmp 我想遍历 bmp 并将其分成小的 1x8 列以获
  • 批量更新 SQL Server C#

    我有一个 270k 行的数据库 带有主键mid和一个名为value 我有一个包含中值和值的文本文件 现在我想更新表格 以便将每个值分配给正确的中间值 我当前的方法是从 C 读取文本文件 并为我读取的每一行更新表中的一行 必须有更快的方法来做
  • 等待线程完成

    private void button1 Click object sender EventArgs e for int i 0 i lt 15 i Thread nova new Thread Method nova Start list
  • 私有模板函数

    我有一堂课 C h class C private template
  • std::async 与重载函数

    可能的重复 std bind 重载解析 https stackoverflow com questions 4159487 stdbind overload resolution 考虑以下 C 示例 class A public int f
  • HttpWebRequest 在第二次调用时超时

    为什么以下代码在第二次 及后续 运行时超时 代码挂在 using Stream objStream request GetResponse GetResponseStream 然后引发 WebException 表示请求已超时 我已经尝试过
  • 如何从main方法调用业务对象类?

    我已将代码分为业务对象 访问层 如下所示 void Main Business object public class ExpenseBO public void MakeExpense ExpensePayload payload var
  • gcc 的配置选项如何确定默认枚举大小(短或非短)?

    我尝试了一些 gcc 编译器来查看默认枚举大小是否很短 至少一个字节 强制使用 fshort enums 或无短 至少 4 个字节 强制使用 fno short enums user host echo Static assert 4 si
  • 线程和 fork()。我该如何处理呢? [复制]

    这个问题在这里已经有答案了 可能的重复 多线程程序中的fork https stackoverflow com questions 1235516 fork in multi threaded program 如果我有一个使用 fork 的
  • 使用 GhostScript.NET 打印 PDF DPI 打印问题

    我在用GhostScript NET http ghostscriptnet codeplex com打印 PDF 当我以 96DPI 打印时 PDF 打印效果很好 但有点模糊 如果我尝试以 600DPI 打印文档 打印的页面会被极大地放大
  • 防止在工厂方法之外实例化对象

    假设我有一个带有工厂方法的类 class A public static A newA Some code logging return new A 是否可以使用 a 来阻止此类对象的实例化new 那么工厂方法是创建对象实例的唯一方法吗 当
  • 如何正确使用 std::condition_variable?

    我很困惑conditions variables以及如何 安全 使用它们 在我的应用程序中 我有一个创建 gui 线程的类 但是当 gui 是由 gui 线程构造时 主线程需要等待 情况与下面的函数相同 主线程创建互斥体 锁和conditi

随机推荐

  • GCC编译选项补充

    一 出错检查和警告提示选项 pedantic error 允许发出ANSIC标准所列的全部错误信息 w 关闭所有警告 Wall 允许发出GCC提供的所有有用的报警信息 Werror 把所有的告警信息转化为错误信息 并在告警发生时终止编译过程
  • vue---制作表格+分页功能

    小白第一次尝试使用vue制作分页功能 分为两个部分 一个是表格部分 一个是下面分页的按钮部分 表格部分用最熟悉的html标签table table tr th 字母 th tr tr td td td td tr table
  • 移动端H5页面返回并且刷新页面(BFcache)

    项目中的需求 点击浏览器中的返回按钮 要让页面重新加载资源 因为这部分的资源每次去加载的内容都不一样 如果返回的时候 还是看到原先的内容 那做这个内容块的意义就很小了 而如果用户看完了这部分内容 再返回来的时候 这个地方换成了新的内容 这样
  • Could not resolve all dependencies for configuration ':app:_debugApk'

    问题 FAILURE Build failed with an exception What went wrong A problem occurred configuring project app gt Could not resolv
  • mysql常用命令,mysql数据类型和Java数据类型对应

    一 创建数据库 1 dos命令打开数据库 mysql u root pok 2 查看数据库 show databases 3 创建数据库 假设数据库表名abc create database abc 4 删除数据库 drop databas
  • 刷脸支付让用户与商家距离更进一步

    商业世界中 支付 往往不仅是支付 正如支付宝的诞生让网络交易变得可靠 线下二维码直接带动了移动支付的兴起 刷脸支付则让用户与商家的距离更进一步 以友宝 留夫鸭为代表的线下零售企业正成为这次支付变革中的首批获益者 率先完成了自身零售模式的进化
  • netdiscover使用

    介绍 Netdiscover是一种网络扫描工具 通过ARP扫描发现活动主机 可以通过主动和被动两种模式进行ARP扫描 通过主动发送ARP请求检查网络ARP流量 通过自动扫描模式扫描网络地址 对此我们可以对其网段进行获取存活主机进行信息收集
  • yolov5组件笔记

    深度学习模型组件 深度可分离卷积 瓶颈层Bottleneck CSP瓶颈层BottleneckCSP ResNet模块 SPP空间金字塔池化模块 目录 1 标准卷积 Conv BN activate 2 DWConv深度可分离卷积 3 Bo
  • 部署ML/DL 模型到一个consolidated AI演示

    关键字 IRIS IntegratedML Flask FastAPI TensorFlow Serving HAProxy Docker Covid 19 目的 过去几个月里 我们提到了一些深度学习和机器学习的快速演示 包括一个简单的 C
  • Python pygame窗口无法退出的问题-解决办法

    大部分Python学习课程都会推荐学习pygame库 笔者在学习过程中 遇到了一个小问题 就是按照原来的code来进行 见下 无法正常退出窗口 if event type pygame QUIT sys exit 稍微修改下这样就可以了 i
  • close-on-exec标志介绍

    在执行exec 之前 程序有时需要确保关闭某些特定的文件描述符 尤其是在特权进程中调用exec 来启动一个未知程序时 并非自己编写 抑或是启动程序并不需要使用这些已打开的文件描述符时 从安全编程的角度出发 应当在加载新程序之前确保关闭那些不
  • 视频技术阐释

    目录 一 视频定义 二 视频原理 三 视频中的图像表达原理 四 视频的基础参数 帧 长宽比 分辨率 帧率 码率 重采样率 色深 五 视频的高低频 六 视频编码与格式 七 视频评价 八 视频开发库 九 视频协议 十 常用视频编辑软件 一 视频
  • Golang面试题整理

    1 make和new区别 make和new都是go的内置函数 builtin包下 func new Type Type 内建函数new分配内存 其第一个实参为类型 而非值 其返回值为指向该类型的新分配的零值的指针 func make Typ
  • stm32输出比较模式与PWM模式总结

    文章目录 前言 一 输出比较模式和PWM模式 二 PWM模式 1 原理 2 配置cubemx 3 代码及验证 三 输出比较模式 1 原理 2 配置cubemx 2 代码及验证 总结 前言 最近因为从标准库过渡到hal库 又重新温习了一遍定时
  • SQL 2000递归查询

    网上的做法都是不能以NUL为关键字进行递归查询 现修改如下 可以任意进行递归 记录备忘 查询指定节点及其所有子节点的函数 alter FUNCTION GetLevel ID nvarchar 36 RETURNS t Level TABL
  • 13 Binder通信之ServiceManager

    Binder通信之ServiceManager 一 前言 Android系统中存在很多service 当某个应用调用系统某个service的功能时 往往向系统发出请求 调用该服务的外部接口 这种外部接口我们通常叫做代理接口 也就是说要拿到目
  • WinRAR在DOS下压缩/解压缩的使用方法

    用实例来说明问题 我的WinRAR路径 C Program Files WinRAR WinRAR exe 用法 rar lt 命令 gt lt 开关 1 gt lt 开关 N gt lt 压缩文件 gt lt 文件 gt lt 列表文件
  • Fortran 77

    FORTRAN结构化程序设计 第一章 FORTRAN语言程序设计初步 1 1 Fortran语言发展概况 1 2 简单的FORTRAN程序分析 1 3 FORTRAN源程序书写格式 1 4 Fortran程序的编辑与运行 1 5 常量 1
  • Java 集合框架

    1 集合框架概述 集合和数组的区别 数组的弊端 数组初始化后 长度不可变 不利于扩展 数组中提供的属性和方法少 不便于进行添加 删除 插入等操作 而且效率不搞 同时无法直接获取存储元素的个数 数组存储的数据是有序的 可以重复的 gt 存储数
  • 图文详解YUV420数据格式

    原文地址 http www cnblogs com azraelly archive 2013 01 01 2841269 html 1 YUV简介 YUV定义 分为三个分量 Y 表示明亮度 Luminance或Luma 也就是灰度值 而