GPU 实现 RGB -- YUV 转换

前言

RGB --> YUV 转换的公式是现成的,直接在 CPU 端转换的话,只需要遍历每个像素,得到新的 YUV 值,根据其内存分布规律,合理安排分布即可。然而在 CPU 端进行转换,存在的问题运行效率太低,无法满足高效转换的需求。我们将目光投向拥有流水线体系的支持高速浮点数计算的硬件——GPU.

转换公式如下:

GPU 上面的实现

考虑在 GPU 上执行 RGB --> YUV 转换。GPU 的流水线操作:

vertices
----> Pipeline ----> Out color
texture

所以将 RGB 图像作为纹理输入,流水线输出我们需要的 YUV 数据。前面一部分很好理解,图像作为唯一的纹理输入,没有别的选项。后面一部分的话,需要在输出的时候输出我们需要的 YUV 数据即可,在 fragment shader 中的输出按常理就是每一个 fragment 的颜色,为实现读取像素是 YUV 的目标,要调整输出的数据。

考虑 YUV 格式内存分布,以 NV12 为例,一张图片占用内存大小为:width x height * 3 / 2 (我们认为图像的宽为 width 高为 height). 如果是 RGBA 的格式存储的话,占用的内存空间大小是:width x height x 4 (因为 RGBA 一共4个通道)。如果我们把 OpenGL renderbuffer 大小设置成等于图像的大小,那输出的大小就是 RGBA 那一种的大小,和 YUV 格式的是对不上的。考虑 YUV 的分布特点,设计输出的宽高为 (width / 4, height * 3 / 2). 示意图如下:

Memory of a frame (yuv format)

  width / 4
|-------------|
| |
| | h
| chrominance |
| |
|-------------|
| |
| luminance | h / 2
|-------------|

因为每一个 out color 含有四个分量 RGBA 所以将宽度设为 width / 4, 那么正好每一行的像素就是原来 width 的数量。在 fragment shader 内部计算的时候,需要考虑当前处理的单个 fragment 是属于 chrominance OR luminance, 可以用纹理坐标的 t 值的大小来判断。

Chrominance

所谓的 RGBA 四个分量实际上代表四个不同的像素的 chrominance 值,也就是说需要做一定的 offset, 来获取到当前像素附近的像素的值,我先假定 offset 为 1.0f / width. 故四个分量如下:

  1. (s, t)
  2. (s + off, t)
  3. (s + off x 2.0f, t)
  4. (s + off x 3.0f, t)

根据四个像素的 RGBA 值计算出四个 Y 通道的数据作为这个 fragment 的输出颜色。

Luminance

仍然是一个像素四个分量,但是现在代表的是两对 UV 分量。因为根据一个 RGBA 就可以算出 YUV 值,所以此处只需要做一个偏移。

  1. (s, t)
  2. (s + off x 2, t)

这里 offset 的设置可以乘 1 或 2 或 3,我觉得都可以,我只是取中道选择了 2. 将上面两个像素的 UV 分量作为这个 fragment 的输出颜色。

readback pixel

最终用 glReadpixels() 函数,将我们输出的颜色读回来,就完成了。

补充

实际操作中遇到的一个问题是,如果设置了 GL_BLEND, 最终输出的颜色会是混合以后的颜色,记得一定要确认关闭了 blending.

Written with StackEdit.

GPU 实现 RGB -- YUV 转换 (OpenGL)的更多相关文章

  1. 最简单的视音频播放示例5:OpenGL播放RGB/YUV

    本文记录OpenGL播放视频的技术.OpenGL是一个和Direct3D同一层面的技术.相比于Direct3D,OpenGL具有跨平台的优势.尽管在游戏领域,DirectX的影响力已渐渐超越OpenG ...

  2. 最简单的视音频播放演示样例5:OpenGL播放RGB/YUV

    ===================================================== 最简单的视音频播放演示样例系列文章列表: 最简单的视音频播放演示样例1:总述 最简单的视音频 ...

  3. 【视频处理】YUV与RGB格式转换

    YUV格式具有亮度信息和色彩信息分离的特点,但大多数图像处理操作都是基于RGB格式. 因此当要对图像进行后期处理显示时,需要把YUV格式转换成RGB格式. RGB与YUV的变换公式如下: YUV(25 ...

  4. YUV转换成RGB算法

    YUV转换成RGB void yuvtorgb ( double *rgb,unsigned char *yuv) { int i; rgb[] = ] + + ] - ); // r rgb[] = ...

  5. YUV与RGB格式转换

    YUV格式具有亮度信息和色彩信息分离的特点,但大多数图像处理操作都是基于RGB格式. 因此当要对图像进行后期处理显示时,需要把YUV格式转换成RGB格式. RGB与YUV的变换公式如下: YUV(25 ...

  6. YUV RGB 格式转换

    第一个公式是RGB转YUV(范围0-255)时用的,第二个公式是用在YUV转换RGB(范围0-255)时用的.1. Y = ; U = -; V = ; 黑色:Y=16 ,U= V =128 红色:Y ...

  7. 【图像处理与医学图像处理】YUV与RGB格式转换速度几种方法对比

    [视频处理]YUV与RGB格式转换 YUV格式具有亮度信息和色彩信息分离的特点,但大多数图像处理操作都是基于RGB格式. 因此当要对图像进行后期处理显示时,需要把YUV格式转换成RGB格式. RGB与 ...

  8. 【DSP开发】【VS开发】YUV与RGB格式转换

    [视频处理]YUV与RGB格式转换 YUV格式具有亮度信息和色彩信息分离的特点,但大多数图像处理操作都是基于RGB格式. 因此当要对图像进行后期处理显示时,需要把YUV格式转换成RGB格式. RGB与 ...

  9. Android平台Camera实时滤镜实现方法探讨(三)--通过Shader实现YUV转换RBG

    http://blog.csdn.net/oshunz/article/details/50055057 文章例如该链接通过将YUV分成三个纹理,在shader中取出并且经过公式变换,转换成RGB.我 ...

随机推荐

  1. [转]python json.dumps 中的ensure_ascii 参数引起的中文编码

    本文转自: 梁小白博客(http://biangbiang.cnblogs.com) 在使用json.dumps时要注意一个问题 >>> import json >>&g ...

  2. python爬虫之requests模块介绍

    介绍 #介绍:使用requests可以模拟浏览器的请求,比起之前用到的urllib,requests模块的api更加便捷(本质就是封装了urllib3) #注意:requests库发送请求将网页内容下 ...

  3. jQuery之开关灯示例

    准备jquery-3.2.1.js文件 <!DOCTYPE html> <html lang="en"> <head> <meta cha ...

  4. 认识Sass和Compass

    第一章 Sass和Compass让样式表重焕青春 // 内容概要// 开始学习Sass和动态样式表// 用Sass更高效地写样式表// Compass简介// 用Compass迎接工程实践中的样式挑战 ...

  5. Open Judge 2750 鸡兔同笼

    2750:鸡兔同笼                                                                                            ...

  6. 洛谷 P1308 统计单词数【字符串+模拟】

    P1308 统计单词数 题目描述 一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数. 现在,请你编程实现这一功能,具体要求是:给定 ...

  7. 喵哈哈村的魔法考试 Round #1 (Div.2) 题解&源码(A.水+暴力,B.dp+栈)

    A.喵哈哈村的魔法石 发布时间: 2017年2月21日 20:05   最后更新: 2017年2月21日 20:06   时间限制: 1000ms   内存限制: 128M 描述 传说喵哈哈村有三种神 ...

  8. UVA 1030 - Image Is Everything【模拟+思维+迭代更新】

    题目链接:uva 1030 - Image Is Everything 题目大意:有一个最大为n*n*n的立方体的一个不规整立体,由若干个1*1*1的小正方体构成(每一个小正方体被涂成不同的颜色),给 ...

  9. 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 F. Trig Function(切比雪夫多项式+乘法逆元)

    题目链接:哈哈哈哈哈哈 _(:з」∠)_ _(:з」∠)_ _(:з」∠)_ _(:з」∠)_ _(:з」∠)_ 哈哈哈哈哈哈,从9月16日打了这个题之后就一直在补这道题,今天终于a了,哈哈哈哈哈哈. ...

  10. sscanf()用法

    http://blog.chinaunix.net/uid-26284412-id-3189214.html #include<cstdio> #include<cstring> ...