彻底弄懂I420格式

YUV的概念

YUV 和我们熟知的 RGB 类似,是一种颜色编码格式。它主要用于电视系统和模拟视频邻域(如 Camera 系统)。YUV 包含三个分量,其中 Y 表示明亮度(Luminance 或 Luma),也就是灰度值。而 U 和 V 则表示色度(Chrominance 或 Chroma),作用是描述图像色彩及饱和度,用于指定像素的颜色。没有 UV 分量信息,一样可以显示完整的图像,只不过是黑白的灰度图像。YUV 格式的好处是很好地解决了彩色电视机与黑白电视机的兼容问题(当只要Y分量时就是黑白图像)。YCbCr,YPbPr等专有名词都可以称为YUV。

YUV的格式

YUV的格式取决采样方式

YUV的采样方式

  • 4:4:4表示完全取样(每一个Y对应一组UV分量)
  • 4:2:2表示2:1的水平取样,垂直完全采样(每两个Y共用一组UV分量)
  • 4:2:0表示2:1的水平取样,垂直2:1采样(每四个Y共用一组UV分量)
  • 4:1:1表示4:1的水平取样,垂直完全采样(每四个Y共用一组UV分量)

YUV的存储格式

我们主要关心的是如何处理YUV数据,所以最关心的是YUV数据的存储格式。内存中存储的方式包括两种:

  1. planar 格式:先连续存储所有像素点的 Y 分量,紧接着存储所有像素点的 U 分量,再是V分量(当然不同存储格式的UV的先后顺序是不一样的,如I420的V在U后,YV12则是U在V后)。

  2. packed 格式:每个像素的Y,U,V分量交替存储。

Y,U,V分量存储时的先后顺序的不同,代表了不同的格式,以下列出了几种常见的YUV格式:

  • YUYV(属于YUV422)
    在这里插入图片描述
    两个Y共用一组UV分量。Y,U,V分量交替存储。

  • UYVY(属于YUV422)

在这里插入图片描述
可以看到与YUYV的分量的顺序不一样。

  • YUV422P(属于YUV422)
    在这里插入图片描述
    是Planar存储模式,依次是Y,U,V。U分量在V分量之前
YUV420

根据U分量和Y分量的位置不同,也分为几种类型,常见的如下:

  • YV12(属于YUV420)

在这里插入图片描述
是Planar存储模式,依次是Y,V,U。V分量在U分量之前。

  • NV12(属于YUV420)

在这里插入图片描述
先是Y,在是U,V分量交替出现

一个简易存储示意图

I420: YYYYYYYY UU VV    =>YUV420P
YV12: YYYYYYYY VV UU    =>YUV420P
NV12: YYYYYYYY UVUV     =>YUV420SP
NV21: YYYYYYYY VUVU     =>YUV420SP

YUV420sp与YUV420p的不同之处在,存储UV分量时,YUV420sp中的UV分量是交替存储。

处理I420

I420属于YUV420P(存储格式为Planar),先是Y分量,再依次是U分量,V分量

这种格式很常用,在x264/265的中要求传入的源数据就是这种格式。在libyuv中,进行YUV图像处理(缩放,剪切,旋转)也是要求以这种格式传入。ffmpeg解码h264/265后数据也是这种格式。这种格式也可以直接通过D3D,OpenGL进行渲染。

计算占用的字节大小

一个分量占用一个字节,每一个象素点对应一个Y分量,四分之一个U分量,四分之一个V分量。所以分辨率为w*h的I420格式,Y的字节数为 w*h, U的字节数为w*h/4,V的字节数大小为w*h/4,总字节数即为w*h*3/2

定位像素数据

要处理I420的数据,首先要能定位到像素分量数据。一个典型的场景是,通过freetype在YUV图像上加字幕时,这是需要将指定坐标点的像素替换为freetype返回的字体图数据。

那么下面是取像素点YUV(I420格式)分量数据的公式(Planar存储方式):

size.total = size.width * size.height;
y = yuv[position.y * size.width + position.x];
u = yuv[(position.y / 2) * (size.width / 2) + (position.x / 2) + size.total];
v = yuv[(position.y / 2) * (size.width / 2) + (position.x / 2) + size.total + (size.total / 4)];

size.width/2为U分量和Y分量的步长

转一张很直观的I420存储的示意图。Y,U,V相同颜色的表述是同一像素的分量。可以结合这个图套用上面的公式推算一下:

在这里插入图片描述

一种常用的YUV数据表示方法

如果直接分配一段内存用以存储图像数据(比如I420格式),是没法知道这段内存的YUV分量特点的(每个分量的数据起始及长度)。那么我们可以下面这种方式定义数据结构来解释存储结构:

enum enImageFmt
{
    enImageFmt_YUV420P
    ...
};

struct ImageSize
{
    int iWidth;
    int iHeight;
};

struct VideoFrame
{
    //Image的格式
    enImageFmt fmt;
    //图像的分辨率
    ImageSize Size;
    //分别指向Y,U,V分量的开头
    unsigned char *data[3];
    //分别指示Y,U,V分量一行(步长)数据大小
    unsigned short linesize[3];
}

//如下的一个示例代码
//指针pImage指向一幅YUV420P格式的图像,通过该结构体指示它的内存结构

VideoFrame frame;
frame.fmt = enImageFmt_YUV420P;
frame.Size.w = w;
frame.Size.h = h;
//Y分量的步长
frame.linesize[0] = w;
//U分量的步长(其长度就是Y分量步长的一半,同理V分量)
frame.linesize[1] = w/2;
//V分量的步长
frame.linesize[2] = w/2;
	
//那么data[0]指向的就是Y数据的起始
frame.data[0] = (unsigned char*)pImage;
//U数据的起始
frame.data[1] = frame.data[0] + frame.linesize[0]*h;
//V数据的起始
frame.data[2] = frame.data[1] + frame.linesize[1]*h/2;

该结构体不止可以指示YUV420P的结构,也可以指示其它YUV格式的结构。在ffmpeg中也有类型的结构定义。

总结:

虽然主要是讲解的如果处理I420格式,但是前面介绍了几种不同YUV的存储格式。可以结合存储示意图,类推出如何处理其它YUV格式数据。

参考

https://zh.wikipedia.org/wiki/YUV

https://www.cnblogs.com/azraelly/archive/2013/01/01/2841269.html

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
BERT(Bidirectional Encoder Representation from Transformers)是一种在NLP领域中非常受欢迎的模型。它在2018年10月底由Google发布,并在11项NLP任务中表现出卓越的性能。\[1\] BERT的设计基于Transformer模型,它采用了双向编码器来学习上下文相关的词向量表示。与传统的词向量模型(如word2vec)相比,BERT能够更好地捕捉词语之间的语义关系和上下文信息。\[2\] BERT的训练过程包括两个阶段:Masked LM和下一句预测。在Masked LM阶段,BERT会随机遮盖输入文本中的一些词语,然后通过上下文来预测这些被遮盖的词语。在下一句预测阶段,BERT会判断两个句子是否是连续的。通过这两个任务的训练,BERT能够学习到更全面的语义表示。\[2\] BERT的优势在于它能够在各种NLP任务中进行迁移学习。通过将BERT的预训练模型与特定任务的训练数据进行微调,可以在下游任务中取得很好的性能。这种迁移学习的策略使得BERT成为了目前许多NLP任务的最优解决方案。\[2\] 总结来说,BERT是一种基于Transformer模型的双向编码器,通过预训练和微调的方式,在各种NLP任务中取得了卓越的表现。它的设计使得它能够更好地捕捉词语之间的语义关系和上下文信息,从而提高了NLP任务的性能。\[1\]\[2\] #### 引用[.reference_title] - *1* *3* [彻底搞懂Bert](https://blog.csdn.net/Enjoy_endless/article/details/89226190)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [转:【NLP】彻底搞懂BERT](https://blog.csdn.net/joeland209/article/details/100189836)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mo4776

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值