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. Java 写三角形 空心三角形 菱形 空心菱形

    闲来无事,练习了一下Java基础中的循环语句.练习循环语句,当然少不了,用*打印出来三角形.空心三角形.菱形等这样的几何图形. 粗心大意,失误两次: 一.三角形 遇到一些小问题: 二.金字塔 由于三角 ...

  2. CSS中水平居中的方法

    居中是我们在css中经常遇到的问题,一般有水平居中.垂直居中.垂直水平居中这3种情况,那么今天首先就来对学习到的水平居中的方法做个总结笔记. css水平居中 text-align:center 它的效 ...

  3. SP3精密星历简介

    IGS精密星历采用sp3格式,其存储方式为ASCII文本文件,内容包括表头信息以及文件体,文件体中每隔15 min给出1个卫星的位置,有时还给出卫星的速度.它的特点就是提供卫星精确的轨道位置.采样率为 ...

  4. Python_day1

    一.HelloWorld >>>print("Hello World!") >>>Hello World! 二.变量    1.什么是变量 : ...

  5. org.eclipse.jdi.TimeoutException:Timeout occurred while waiting for packet 1983.occurred

    eclipse 增大junit内存配置 现象:eclipse在junit测试的时候出现如下错误 org.eclipse.jdi.TimeoutException:Timeout occurred wh ...

  6. <魔域>按键精灵脚本

    用了三天时间才写完,实现了通过图片识别读取坐标数值,自动寻路等简单功能. 主要的难点在于游戏中的坐标系,和电脑屏幕的坐标系存在三维旋转关系,难以换算. //全局变量:第一个数左上右下坐标 Global ...

  7. [51nod1440]迈克打电话

    有n只熊,从1到n进行编号. 第i只熊的电话号码是si.每只熊会给那些电话号码是他的子串的熊打电话(可能会给自己打). call(i, j) 表示第i只熊给第j只熊打电话的次数,也就是第j个串在第i个 ...

  8. NowCoder牛客练习赛7-A.骰子的游戏 B.购物-优先队列

    A.骰⼦的游戏 时间限制:C/C++ 1秒,其他语言2秒空间限制:C/C++ 32768K,其他语言65536K64bit IO Format: %lld 题目描述 在Alice和Bob面前的是两个骰 ...

  9. Victor and World(spfa+状态压缩dp)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5418 Victor and World Time Limit: 4000/2000 MS (Java/ ...

  10. js获取不带单位的像素值

    所谓获取不带单位的像素值就是获取比如元素的宽度.高度.字体大小.外边距.内边距等值但是去掉像素单位. 比如:某一个元素的宽度是100px,现在我要获取这个这个值但是不带单位“px”,对于这种问题你会怎 ...