当前位置: 首页 > news >正文

YUV 与 颜色空间转换

BT601 和 BT709

由于在处理相机实时图像数据时,需要将相机采集的YUV数据转换为RGB,根据GPUImage的源码看到是有三种转换矩阵用于将YUV数据转换成RGB数据,分别是

// BT.601, which is the standard for SDTV.
GLfloat kColorConversion601Default[] = {
1.164,  1.164, 1.164,
0.0, -0.392, 2.017,
1.596, -0.813,   0.0,
};
// BT.601 full range (ref:http://www.equasys.de/colorconversion.html)
GLfloat kColorConversion601FullRangeDefault[] = {
1.0,    1.0,    1.0,
0.0,    -0.343, 1.765,
1.4,    -0.711, 0.0,
};

// BT.709, which is the standard for HDTV.
GLfloat kColorConversion709Default[] = {
1.164,  1.164, 1.164,
0.0, -0.213, 2.112,
1.793, -0.533,   0.0,
};

可以看到其中两个比较奇特的关键字即 601 和 709,同时还有 FullRange 。

fullRange 和 videoRange

在apple关于图像pixelformat的定义中有关于yuv格式的420v和420f的定义

kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange = '420v', 
/* Bi-Planar Component Y'CbCr 8-bit 4:2:0, video-range (luma=[16,235] chroma=[16,240]).  baseAddr points to a big-endian CVPlanarPixelBufferInfo_YCbCrBiPlanar struct */
kCVPixelFormatType_420YpCbCr8BiPlanarFullRange  = '420f', 
/* Bi-Planar Component Y'CbCr 8-bit 4:2:0, full-range (luma=[0,255] chroma=[1,255]).  baseAddr points to a big-endian CVPlanarPixelBufferInfo_YCbCrBiPlanar struct *

而fullRange和videoRange本身的意义是YUV颜色空间中 亮度部分 Y 的取值范围,fullRange的取值范围为luma=[0,255] chroma=[1,255],而videoRange是luma=[16,235] chroma=[16,240],另外chroma(Cb,Cr)即色度部分与亮度部分不同,始终为fullRange。

YUV

初识颜色空间时,YUV应该是除了大家从小耳濡目染的RGB之外,最让人不明觉历的颜色空间了,它高端大气的名字再加上YUV本身420,422,411这些不同变形 所显示的复杂度更容易让人望而却步。

不过本着天下事有难易乎,为之则难者亦易矣,不为则易者亦难矣的态度,我们来对YUV进行一个简明的学习。

YUV是将人眼的感知考虑进来的用于对颜色彩色图像进行编码的颜色空间,根据维基百科的说法简化来说,YUV与YCbCr这两个概念之间界限比较模糊且是有部分重叠的,因为YUV是用于电视系统中模拟颜色信息的编码,而YCbCr适用于对以MPEG及JPEG为代表的视频及静态图片的压缩及传输等场景下对颜色信息的数字编码。

而现在YUV通常用于计算机工业中称呼使用YCbCr进行编码的文件格式。而一个小常识是YUV3个分量分别都并不是缩写,而只是对应于xyz的一种坐标系代号而已。

YUV和RGB之间的转换

SDTV with BT601

BT601是用数字格式编码交错的模拟视频信号的标准,定义于SDTV标准中

//Wr,Wg,Wb,Umax,Vmax均为对应于各BT标准的
Wr = 0.299
Wg = 1 - Wr - Wb = 0.587
Wb = 0.114
Umax = 0.436
Vmax = 0.615

HDTV with BT709

BT 709标准调整了

Wr = 0.2126
Wr = 0.0722

GPUImage框架中同款的YCbCr与RGB转换规则, 应用于数字颜色信息编码的YCbCr应用于SDTV时,标准为BT601

332c941fec6378e65d84ae6e774e8183.png

在这种videoRange格式中,亮度和色度空间都留有footroom和headroom,部分原因是为了与模拟视频设备结合的场景,而一般典型的比如JPEG图像使用如下的颜色格式full range。

733ef4b02c841f826cb9ead02772ef37.png

而对于HDTV,标准为BT709,由于使用的参数不同,与SDTV一样留有headroom和footroom。

5446d70374f839ff03a139a180bf583f.png

所以对于videorange和fullrange对应的转换为RGB的fragmentshader分别为

//fullrange
varying highp vec2 textureCoordinate;

uniform sampler2D luminanceTexture;
uniform sampler2D chrominanceTexture;
uniform mediump mat3 colorConversionMatrix;

void main()
{
 mediump vec3 yuv;
 lowp vec3 rgb;
 
 yuv.x = texture2D(luminanceTexture, textureCoordinate).r;
 yuv.yz = texture2D(chrominanceTexture, textureCoordinate).ra - vec2(0.5, 0.5);
 rgb = colorConversionMatrix * yuv;
 
 gl_FragColor = vec4(rgb, 1);
}

//video range
varying highp vec2 textureCoordinate;

uniform sampler2D luminanceTexture;
uniform sampler2D chrominanceTexture;
uniform mediump mat3 colorConversionMatrix;

void main()
{
 mediump vec3 yuv;
 lowp vec3 rgb;
 
 yuv.x = texture2D(luminanceTexture, textureCoordinate).r - (16.0/255.0);
 yuv.yz = texture2D(chrominanceTexture, textureCoordinate).ra - vec2(0.5, 0.5);
 rgb = colorConversionMatrix * yuv;
 
 gl_FragColor = vec4(rgb, 1);
}

作者:纵横而乐

来源:https://www.jianshu.com/u/a0bb5a5215e4

706c5b49867280ac9d83e67cfe829617.png

accc775751287d9e9b5e9f0af476d258.png

一个音视频领域专业问答的小圈子!

加我微信 ezglumes 拉你入技术交流群

推荐阅读:

音视频开发工作经验分享 || 视频版

OpenGL ES 学习资源分享

开通专辑 | 细数那些年写过的技术文章专辑

Android NDK 免费视频在线学习!!!

你想要的音视频开发资料库来了

推荐几个堪称教科书级别的 Android 音视频入门项目

觉得不错,点个在看呗~

ecbdc67e351aee284ece806443ecc7f9.gif

相关文章:

  • 原创干货 | 入门或者转行音视频,应该要怎么做?
  • 上手 GAMES 104 课程 Pilot 游戏引擎~~
  • 关于音视频里面的 解码帧率 和 渲染帧率
  • 将音视频中的花屏、绿屏、黑屏问题一网打尽
  • 关于直播、WebRTC、FFmpeg 的那些事~~
  • 干货 | 快速抽取缩略图是怎么练成的?
  • 没有操作系统程序可以运行起来吗?
  • 重学音视频?认识 MP4 视频(上)
  • 重学音视频?认识 MP4 视频(下)
  • 关于 Android 渲染你应该了解的知识点
  • Android 视频编辑解析库 MP4Parser
  • 动态图片加两条白杠就能营造出 3D 效果 ?
  • FFmepg 中错误码的玄机!
  • 如何简单方便地Hook Gradle插件?
  • 十分钟完成安卓 MediaCodec 视频解码
  • [js高手之路]搞清楚面向对象,必须要理解对象在创建过程中的内存表示
  • 2017-08-04 前端日报
  • Java|序列化异常StreamCorruptedException的解决方法
  • leetcode388. Longest Absolute File Path
  • PHP面试之三:MySQL数据库
  • Python打包系统简单入门
  • Python连接Oracle
  • Redis学习笔记 - pipline(流水线、管道)
  • 初探 Vue 生命周期和钩子函数
  • 当SetTimeout遇到了字符串
  • 技术攻略】php设计模式(一):简介及创建型模式
  • 简析gRPC client 连接管理
  • 今年的LC3大会没了?
  • 快速体验 Sentinel 集群限流功能,只需简单几步
  • 前端攻城师
  • 让你成为前端,后端或全栈开发程序员的进阶指南,一门学到老的技术
  • 算法-插入排序
  • 用 vue 组件自定义 v-model, 实现一个 Tab 组件。
  • 正则表达式小结
  • MiKTeX could not find the script engine ‘perl.exe‘ which is required to execute ‘latexmk‘.
  • 分布式关系型数据库服务 DRDS 支持显示的 Prepare 及逻辑库锁功能等多项能力 ...
  • ​力扣解法汇总946-验证栈序列
  • ​软考-高级-系统架构设计师教程(清华第2版)【第12章 信息系统架构设计理论与实践(P420~465)-思维导图】​
  • #{}和${}的区别?
  • (¥1011)-(一千零一拾一元整)输出
  • (02)Hive SQL编译成MapReduce任务的过程
  • (1)(1.13) SiK无线电高级配置(六)
  • (C语言)逆序输出字符串
  • (八)五种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (超详细)语音信号处理之特征提取
  • (附源码)小程序儿童艺术培训机构教育管理小程序 毕业设计 201740
  • (个人笔记质量不佳)SQL 左连接、右连接、内连接的区别
  • (力扣题库)跳跃游戏II(c++)
  • (转)IOS中获取各种文件的目录路径的方法
  • (转)linux自定义开机启动服务和chkconfig使用方法
  • (转)Scala的“=”符号简介
  • (最简单,详细,直接上手)uniapp/vue中英文多语言切换
  • .bat批处理(六):替换字符串中匹配的子串
  • .describe() python_Python-Win32com-Excel
  • .htaccess配置重写url引擎