最近弄了一个读取y4m文件转成yuv的流的事情,记录一些yuv相关的细节

为什么会有yuv

因为我们目前的显示器显示的原理都是三原色,几乎所有的视频数据最后都要转为rgb格式才能渲染到显示屏上,而原始的rgb格式存储太耗费空间

rgb存储空间是每个像素点需要 rbg三个属性,每个属性八个bit来存储,也就是24bit

而yuv则是从另外一个角度描述图片,y是明亮度(灰介值),uv是则是色度,而人眼对色度没有那么敏感,可以通过减少uv的采集从而减少存储

为什么叫yuv?

查了很久,基本可以确认yuv三个字母不是某些缩写,yuv的另一个叫法是Y Cb(cut blue) Cr(Cut red),这一个可以理解的叫法,对于一个图像点(rgb),可以使用y(亮度)和cb(和蓝色的色差)以及cr(和红色的色差)来近似表达;yuv中的uv貌似跟纹理贴图中的uv坐标系有些关联;

减少采集的方式是设定采样比

  • 采样比通常表示为 J:a:b,以表示一个宽为 J 像素、高为 2 像素的采样区域内 Y Cb Cr(Y U V)的采样比:

    • J 表示采样区域的宽度,通常为 4;
    • a 表示第一行色度采样数;
    • b 表示第二行色度采样与第一行色度采样的不同样点数;(零代表Ja0合J0a依次交替,并不是uv某个维度不采样的意思)

上图来源:https://imgs.piasy.com/2018-04-27-sampling_systems_and_ratios.png

压缩比计算示例

简单算下压缩率,如上面的图,4*2 =8个像素,用rbg需要8*3*8=192bit

用yuv444需要8*8(Y)+ 4*2*8(U)+4*2*8(V)=192bit,是一样的

用yuv422需要8*8(Y)+ 2*2*8(U)+2*2*8(V)=128bit,节省了1/3,

用yuv420需要8*8(Y)+ 2*2*8(UV)=96bit,节省了一半(零代表Ja0合J0a依次交替,并不是uv某个维度不采样的意思

YUV 存储格式

YUV 数据有两种存储格式:平面格式(planar format)和打包格式(packed format)。

  • planar: 有时也称 triplanar,有三个 plane,每种分量连续存储,先存储所有的 Y 分量,再存储所有的 Cb 分量,最后存储所有的 Cr 分量(也可以 Cr 在前,Cb 在后);
  • packed: 只有一个 plane,n 个样点的 Y Cb Cr 分量一起存储,接着存储下 n 个样点的分量;n 的取值、其中三种分量的存储方式,也有多种组合;
  • semi planar: 有两个 plane,先存储所有的 Y 分量,后面 Cb 和 Cr 分量一起存储;

i420

I420 的采样比是 4:2:0,它是 planar 存储方式,分量存储顺序依次是 Y, Cb, Cr

nv12(ios)

NV12 的采样比是 4:2:0,它是 semi planar 存储方式,先存储 Y 分量,后面 Cb 和 Cr 分量一起存储,Cb 在前,Cr 在后

nv21(Android)

NV21 和 NV12 类似,采样比是 4:2:0,也是 semi planar 存储方式,先存储 Y 分量,后面 Cb 和 Cr 分量一起存储,只不过 Cr 在前,Cb 在后

i420 转nv21

从上面的介绍可以看到,i420是yuv分开存储,y是一致的,我们只要分别拿到u和v,改变一些顺序即可从i420转到nv21

  private void I420ToNv21(byte[] i420bytes, int width, int height) {
byte[] nv21bytes = new byte[i420bytes.length];
int y_len = width * height;
int uv_len = y_len / 4;
System.arraycopy(i420bytes, 0, nv21bytes, 0, y_len);
for (int i =0; i < uv_len; i++) {
byte u = i420bytes[y_len + i];
byte v = i420bytes[y_len + uv_len + i];
nv21bytes[y_len + i*2] = v;
nv21bytes[y_len + i*2 +1] = u;
}
System.arraycopy(nv21bytes, 0, i420bytes, 0, nv21bytes.length);
nv21bytes = null;
}

stride 或 pitch

YUV 数据在内存中存储时,每行像素的数据后面可能还有填充字节,这主要是因为有些系统/环境/操作对内存的字节对齐有要求,比如 64 字节对齐,那么宽度为 720 像素的图像,一行就不满足 64 对齐的要求,那就要填充到 768 像素。存储一行像素所需的字节数,就叫 stride,也叫 pitch。比如这里举的例子,宽为 720,stride 或 pitch 就是 64。

rgb to yuv

yuv to rgb

y4m

y4m是yuv文件的一种存储格式,上面的yuv都是整个图片或者视频的yuv,y4m文件中有明确的帧的划分,处理起来会更方便一些

相信至此,对于yuv的来历、作用以及存储使用,

p

简说yuv的更多相关文章

  1. Video Toolbox:读写解码回调函数CVImageBufferRef的YUV图像

    本文档基于H.264的解码,介绍读写Video Toolbox解码回调函数参数CVImageBufferRef中的YUV或RGB数据的方法,并给出CVImageBufferRef生成灰度图代码.方便调 ...

  2. 【性能优化】优化笔记之一:图像RGB与YUV转换优化

    本文主要介绍如何优化您自己的CODE,实现软件的加速.我们一个图象模式识别的项目,需要将RGB格式的彩色图像先转换成黑白图像.图像转换的公式如下: Y = 0.299 * R + 0.587 * G ...

  3. YUV / RGB 格式及快速转换算法

    1 前言 自然界的颜色千变万化,为了给颜色一个量化的衡量标准,就需要建立色彩空间模型来描述各种各样的颜色,由于人对色彩的感知是一个复杂的生理和心理联合作用 的过程,所以在不同的应用领域中为了更好更准确 ...

  4. YUV格式与RGB格式

    YUV420介绍: YUV420格式是指,每个像素都保留一个Y(亮度)分量,而在水平方向上,不是每行都取U和V分量,而是一行只取U分量,则其接着一行就只取V分量,以此重复(即4:2:0, 4:0:2, ...

  5. yuv rgb 互转 公式 及算法

    1 前言 自然界的颜色千变万化,为了给颜色一个量化的衡量标准,就需要建立色彩空间模型来描述各种各样的颜色,由于人对色彩的感知是一个复杂的生理和心理联合作用的过程,所以在不同的应用领域中为了更好更准确的 ...

  6. FFmpeg简易播放器的实现-最简版

    本文为作者原创:https://www.cnblogs.com/leisure_chn/p/10040202.html,转载请注明出处 基于FFmpeg和SDL实现的简易视频播放器,主要分为读取视频文 ...

  7. YUV视频格式详解(翻译自微软文档)

    原文: https://docs.microsoft.com/en-us/previous-versions/aa904813(v=vs.80) YUV视频格式详解(翻译自微软文档)https://b ...

  8. 经典算法,yuv与rgb互转,查表法,让你的软件飞起来

    代码的运算速度取决于以下几个方面 1. 算法本身的复杂度,比如MPEG比JPEG复杂,JPEG比BMP图片的编码复杂. 2. CPU自身的速度和设计架构 3. CPU的总线带宽 4. 您自己代码的写法 ...

  9. CSharpGL(28)得到高精度可定制字形贴图的极简方法

    CSharpGL(28)得到高精度可定制字形贴图的极简方法 回顾 以前我用SharpFont实现了解析TTF文件从而获取字形贴图的功能,并最终实现了用OpenGL渲染文字. 使用SharpFont,美 ...

随机推荐

  1. WPF DataGrid DataGridTextColumn

    Style设置时,无法绑定到数据,需要这样写 1 <DataGridTextColumn Header="呵呵" Binding="{Binding ID}&quo ...

  2. Java异常02——自定义异常

    Error与Exception与自定义异常 Error与Exception Error Exception 自定义异常 快捷键: ctrl + alt + t  package exception.d ...

  3. C++ //继承中构造和析构顺序

    1 #include <iostream> 2 #include <string> 3 using namespace std; 4 5 class Base 6 { 7 pu ...

  4. [TensorFlow2.0]-张量与常用函数

    本人人工智能初学者,现在在学习TensorFlow2.0,对一些学习内容做一下笔记.笔记中,有些内容理解可能较为肤浅.有偏差等,各位在阅读时如有发现问题,请评论或者邮箱(右侧边栏有邮箱地址)提醒. 若 ...

  5. configmap使用方法

    说明: kubernetes统一配置管理方案configmap,实现将配置文件从容器镜像中解耦,增强应用的可移植性.数据可直接注入pod对象中,为容器所使用,注入方式有挂载为存储卷和传递为环境变量两种 ...

  6. Java 在PPT中插入OLE对象

    PPT幻灯片中支持将文档作为OLE对象插入到PPT幻灯片指定位置,在幻灯片中可直接点击该对象,打开或编辑等.下面以插入Excel工作簿文档为例,介绍如何来插入到幻灯片.   程序运行环境 编译环境:I ...

  7. CVE-2021-21978 VMware View Planner 远程代码执行漏洞通告 | 附 POC

    漏洞简介 VMware 是一家云基础架构和移动商务解决方案厂商,View Planner 是他旗下推出的一款针对view桌面的测试工具.2021年03月02日,VMware 官方披露了 CVE-202 ...

  8. vue项目中踩过的element的坑

    前言:在现在这种大的社会背景下,人们的需求更加的个性化了,而之前为了解放开发复杂的原生开发状态,现有的组件库已经远远不能满足人们高质量的需求了,这两天开发发现了一些element UI交互上的缺陷,当 ...

  9. HTML界的“苏炳添”——详解Canvas优越性能和实际应用

    Google Docs宣布将会把HTML迁移到基于Canvas渲染,这一消息的出现再次把几年前随HTML5诞生的标签重新推到了人们视线之中.Canvas在刚推出时主打的优势就是更快的渲染速度,堪称HT ...

  10. SQL 练习18

    按各科成绩进行排序,并显示排名, Score 重复时保留名次空缺 SELECT t.cid,t.sid,t.score ,COUNT(t1.score)+1 as 排名 from sc as t LE ...