YUV444、YUV422、YUV420知识存档
对于一张图片,对其进行yuv采样存放会有几种格式,常见的有YUV444 YUV422 YUV420
这些格式的显著的区别就是对每个像素的信息采样方式的不同
比如如下的一张图片,每个格子代表一个像素
P0 |
P1 |
P2 |
P3 |
P4 |
P5 |
P6 |
P7 |
P8 |
P9 |
P10 |
P11 |
P12 |
P13 |
P14 |
P15 |
用yuv444采样方式进行采样:
采样每个像素的y、u、v分量,这样导致内存中占用的空间是 width * height *3 的大小
Y0 U0 V0 |
Y1 U1 V1 |
Y2 U2 V2 |
Y3 U3 V3 |
Y4 U4 V4 |
Y5 U5 V5 |
Y6 U6 V6 |
Y7 U7 V7 |
Y8 U8 V8 |
Y9 U9 V9 |
Y10 U10 V10 |
Y11 U11 V11 |
Y12 U12 V12 |
Y13 U13 V13 |
Y14 U14 V14 |
Y15 U15 V15 |
如果是YUV422的采样方式:
采样每个像素的y分量,然后每两个像素采样一次u和v分量,于是u和v分量占用的空间大小分别是原来像素数的一半
那么一帧图象被YUV422采样以后占用的总大小就是 width * height * 2
Y0 U0 |
Y1 V1 |
Y2 U2 |
Y3 V3 |
Y4 U4 |
Y5 V5 |
Y6 U6 |
Y7 V7 |
Y8 U8 |
Y9 V9 |
Y10 U10 |
Y11 V11 |
Y12 U12 |
Y13 V13 |
Y14 U14 |
Y15 V15 |
YUV420的采样方式:
y分量的采样方式与上两种一样,对每个像素进行采样;而u和v分量则变成了每2 * 2个像素取样一次。
比如第一行像素,采样每一个像素的y分量,并每两个像素采样一次u分量,本行不采样v分量。
而下一行像素,采样每一个像素的y分量,并每两个像素采样一次v分量,本行不采样u分量。
于是u和v分量占用的空间大小分别是原来像素数的1/4,占用的总大小就是 width * height * (3 / 2)
Y0 U0 |
Y1 |
Y2 U2 |
Y3 |
Y4 V4 |
Y5 |
Y6 V6 |
Y7 |
Y8 U8 |
Y9 |
Y10 U10 |
Y11 |
Y12 V12 |
Y13 |
Y14 V14 |
Y15 |
可以看出,对于这三种采样方式,每个像素的亮度信息(y分量)都被完整保存。不同的地方就是对色差信息(uv分量)的取舍。
通过上面三种方式对每个像素进行了信息的采样,接下来要考虑如何存储。
YUV的存储方式也分为打包(packed)格式存储和平面(plane)格式存储两种。
这就导致了和上面三种采样方式组合出了很多种令人痛苦的yuv格式。
我的理解,打包格式是以 像素点 为单位,连续存储每个像素点的yuv分量;
而平面格式是以 分量 为单位,将三个分量分别存储在三个数组中;
特别的,平面格式中还有一种半平面(semi-plane)的储存方式,这种方式的uv分量被交替存储在同一个数组里。
先来回顾一下yuv422采样方式:
Y0 U0 |
Y1 V1 |
Y2 U2 |
Y3 V3 |
Y4 U4 |
Y5 V5 |
Y6 U6 |
Y7 V7 |
Y8 U8 |
Y9 V9 |
Y10 U10 |
Y11 V11 |
Y12 U12 |
Y13 V13 |
Y14 U14 |
Y15 V15 |
对于YUV422采样,有以下几种常见的存储方式
YUYV格式(packed):
这是一种打包存储YUV422采出数据的方式
Y0 |
U0 |
Y1 |
V1 |
Y2 |
U2 |
Y3 |
V3 |
Y4 |
U4 |
Y5 |
V5 |
Y6 |
U6 |
Y7 |
V7 |
Y8 |
U8 |
Y9 |
V9 |
Y10 |
U10 |
Y11 |
V11 |
Y12 |
U12 |
Y13 |
V13 |
Y14 |
U14 |
Y15 |
V15 |
UYVY格式(packed):
与YUYV一样,也是一种打包存储YUV422采出数据的方式,只是分量的顺序不同
U0 |
Y0 |
V1 |
Y1 |
U2 |
Y2 |
V3 |
Y3 |
U4 |
Y4 |
V5 |
Y5 |
U6 |
Y6 |
V7 |
Y7 |
U8 |
Y8 |
V9 |
Y9 |
U10 |
Y10 |
V11 |
Y11 |
U12 |
Y12 |
V13 |
Y13 |
U14 |
Y14 |
V15 |
Y15 |
YUV422P(plane)格式
这是针对422采样的平面存储格式
Y0 |
Y1 |
Y2 |
Y3 |
Y4 |
Y5 |
Y6 |
Y7 |
Y8 |
Y9 |
Y10 |
Y11 |
Y12 |
Y13 |
Y14 |
Y15 |
U0 |
U2 |
U4 |
U6 |
U8 |
U10 |
U12 |
U14 |
V1 |
V3 |
V5 |
V7 |
V9 |
V11 |
V13 |
V15 |
如上这种先U后V的存储方式又称为YU16,而先V后U的方式就称为YV16
再来回顾一下yuv420采样方式:
Y0 U0 |
Y1 |
Y2 U2 |
Y3 |
Y4 V4 |
Y5 |
Y6 V6 |
Y7 |
Y8 U8 |
Y9 |
Y10 U10 |
Y11 |
Y12 V12 |
Y13 |
Y14 V14 |
Y15 |
对于420采样的存储格式主要有:
YUV420P格式:
这是针对420采样的平面存储格式
Y0 |
Y1 |
Y2 |
Y3 |
Y4 |
Y5 |
Y6 |
Y7 |
Y8 |
Y9 |
Y10 |
Y11 |
Y12 |
Y13 |
Y14 |
Y15 |
U0 |
U2 |
U8 |
U10 |
||||
V4 |
V6 |
V12 |
V14 |
如上这种先U后V的存储方式又称为YU12,而先V后U就称为YV12
YUV420SP格式:
这是针对420采样的半平面(semi-planer)存储格式
Y0 |
Y1 |
Y2 |
Y3 |
Y4 |
Y5 |
Y6 |
Y7 |
Y8 |
Y9 |
Y10 |
Y11 |
Y12 |
Y13 |
Y14 |
Y15 |
U0 |
V4 |
U2 |
V6 |
U8 |
V12 |
U10 |
V14 |
有了上面比较直观的图片解释,可以来尝试几个简单的图片格式转换
void YUV422toYUV420(unsigned char *yuv420, unsigned char *yuv422, int Y_width, int Y_height)
{int UV_width_422 = Y_width >> 1; //422采样的U和V信号在行方向是隔一个采样一次int UV_height_422 = Y_height; //422采样的U和V信号在列方向是全采样的int UV_width_420 = Y_width >> 1; //420采样的U和V信号在行方向是隔一个采样一次int UV_height_420 = Y_height >> 1; //420采样的U和V信号在列方向是隔一个采样一次int Ylen = Y_width * Y_height; //有多少像素就有多少个Y分量/* YUV422P的存储方式:YYYYYYYYYYYYYYYYUUUUUUUUVVVVVVVV*/unsigned char *p_Y422 = yuv422 ;unsigned char *p_U422 = p_Y422 + Ylen ;unsigned char *p_V422 = p_U422 + Ylen / 2 ;/* YUV420P的存储方式:YYYYYYYYYYYYYYYYUUUUVVVV*/unsigned char *p_Y420 = yuv420 ;unsigned char *p_U420 = p_Y420 + Ylen ;unsigned char *p_V420 = p_U420 + Ylen / 4;//Y分量都是一样的,直接复制memcpy(p_Y420, p_Y422, Ylen);/* 对于一个4*4的YUV422来说,U分量的采样结果是:* U0 X U2 X* U4 X U6 X* U8 X U10 X* U12 X U14 X** 而同样大小的YUV420,U分量的采样结果:* U0 X U2 X* X X X X* U8 X U10 X* X X X X* * 在plane的存储方式下,这两种采样U分量的存放区别是:* YUV422P:* U0 U2|U4 U6|U8 U10|U12 U14* * YUV420P:* U0 U2|U8 U10* 用|隔开不表示在存储中被隔开,仅表示这是一个UV_width_422宽度*/int k = 0 ;unsigned char u1, u2 , v1, v2 ;for ( int i = 0 ; i < UV_height_422 ; i += 2){for ( int j = 0 ; j < UV_width_422 ; j++){// 取422p相邻行的两个U分量的平均,作为420取样的U分量u1 = *(p_U422 + i * UV_width_422 + j);u2 = *(p_U422 + (i + 1) * UV_width_422 + j);// 取422p相邻行的两个V分量的平均,作为420取样的V分量v1 = *(p_V422 + i * UV_width_422 + j);v2 = *(p_V422 + (i + 1) * UV_width_422 + j);*(p_U420 + k * UV_width_420 + j) = ((u1 + u2) >> 1);*(p_V420 + k * UV_width_420 + j) = ((v1 + v2) >> 1);}k++;}
}
需要注意的是上面的YUV422和YUV420都是plane方式存储的
完整代码可以参考我上传的资源,里面有一个简单的main,in case 你懒得自己写。此外还包括一个验证过可用性的YUV420P转YUV422P 方法,不过好像需求量不大,需要的可以下载或者没积分的话就喊我贴上来:
yuv422和yuv420相互转换-C++文档类资源-CSDN下载
接下来看如何将YUYV转成YUV422P
void YUYVtoYUV422P(unsigned char *yuyv, unsigned char *yuv422p, int width, int height) {int y_len = width * height;int yuyv_len = width * height * 2;unsigned char* y_plane = yuv422p;unsigned char* u_plane = yuv422p + y_len;unsigned char* v_plane = u_plane + y_len / 2;// 用于标记目前待处理的是哪个分量int component = 0;for (int index = 0; index < yuyv_len; index++) {// yuyv的存储方式下,分量存储顺序是:// Y U Y V Y U Y Vif (0 == component || 2 == component) {*y_plane++ = yuyv[index];component++;} else if (1 == component) {*u_plane++ = yuyv[index];component++;} else if (3 == component) {*v_plane++ = yuyv[index];component = 0;}}
}
YUV444、YUV422、YUV420知识存档相关推荐
- 音视频编解码: YUV采样格式中的YUV444,YUV422,YUV420理解
YUV各种采样格式的说明 通常我们用RGB表示一种彩色.计算机系统里的LCD显示的数据就是RGB来表示每个像素的颜色. 而在我们生活里,有黑白电视机与彩色电视机两种,拍摄节目源时不可以用两种不同的摄像 ...
- YUV图解 (YUV444, YUV422, YUV420, YV12, NV12, NV21)
如果你认为本系列文章对你有所帮助,请大家有钱的捧个钱场,点击此处赞助,赞助额1元起步,多少随意 锋影 email:174176320@qq.com YUV图解 (YUV444, YUV422, YUV ...
- YUV图解 (YUV444, YUV422, YUV420, YV12, NV12, NV21)-- 转
YUV图解 (YUV444, YUV422, YUV420, YV12, NV12, NV21)
- 图像原始格式(YUV444 YUV422 YUV420)一探究竟
前段时间搞x264编码测试,传参的时候需要告诉编码器我的原始数据格式是什么,其中在x264.h头文件中定义了如下一堆类型. /* Colorspace type */ #define X264_CSP ...
- YUV图解 (YUV444, YUV422, YUV420, YV12, NV12, NV21)
YUV格式有两大类:planar和packed. 对于planar的YUV格式,先连续存储所有像素点的Y,紧接着存储所有像素点的U,随后是所有像素点的V. 对于packed的YUV格式,每个像素点的Y ...
- yuv图解(YUV444,YUV422,YUV420,YV12,NV12,NV21)
参考文章 图解YUV YUV是什么 YUV(444,422,420) And YUV(Packed,Planar,Semi-Planar) 知识点 YUV是用一个称为Y(相当于灰度)的亮度分量和两个色 ...
- YUV和RGB的区别(以及YUV444 YUV422 YUV411 YUV420的介绍)
RGB是构成多种颜色的三基色(红绿蓝),也称为加成色.主要是图像的采集和显示.YUV是优化彩色视频信号的编码和传输,和rgb相比,YUV占用的带宽少. YUV中Y表示的是亮度,是通过RGB输入信号确定 ...
- YUV422/YUV420
YUV三种数据格式占用空间计算: YUV444 ==> YUV444 1920*1080 ==> 1920*1080个Y+1920*1080个U+1920*1080个V = 1920*1 ...
- YUV422 YUV420 Planar Semi-Planar详解
前言 YUV 格式通常有两大类:打包(packed)格式和平面(planar)格式.前者将 YUV 分量存放在同一个数组中, 通常是几个相邻的像素组成一个宏像素(macro-pixel);而后者使用三 ...
- YUV422 YUV420 Planar \ Semi-Planar \ Interleaved
关于yuv 格式 YUV 格式通常有两大类:打包(packed)格式和平面(planar)格式.前者将 YUV 分量存放在同一个数组中, 通常是几个相邻的像素组成一个宏像素(macro-pixel); ...
最新文章
- opencv3 图像处理(一)图像缩放( python与c++ 实现)
- 数据集超越MS COCO,2020智源x旷视Objects365物体检测挑战赛开赛
- spring --AOP
- 2019牛客暑期多校训练营(第九场) E	All men are brothers
- spring restful遇到的问题
- Postgresql日志配置
- [PAT乙级]1030 完美数列
- 打破冷漠僵局文章_研究僵局–第3部分
- Linux中搭建YUM
- 大学c语言基本程序,一个大学C语言试题的简单实现--员工信息管理程序
- file input 移动端选择文件夹_免费 |《MNN For Swift》移动端机器学习实战课程
- php成长之路--1.composer下载依赖
- 几本很不错的C++Builder的电子书
- Windows下QT配置librdkafka
- 目标检测-爬虫-利用百度识图的方法来批量的爬取图片生产数据集
- 最新爱云发卡系统源码公益版
- 解密猫晚直播技术:如何保障全球200多个国家和地区同时在线狂欢?
- java excel 导出数据文件格式无效
- linux mysql 登录报1045_【mysql】linux登录MySQL_报错ERROR_1045_(28000)解决办法
- [Caffe]:关于ReLU、LeakyReLU 、PReLU layer