Android平台Camera实时滤镜实现方法探讨(三)--通过Shader实现YUV转换RBG
http://blog.csdn.net/oshunz/article/details/50055057
文章例如该链接通过将YUV分成三个纹理,在shader中取出并且经过公式变换,转换成RGB。我尝试了下,显示的是灰色的,可能是这篇文章采用的是planar格式的YUV,与Android平台的packed格式的YUV不同,因此需要在纹理绑定处进行数据指针的修改。
之前在一篇13年北大硕士的论文基于android平台实时滤镜的设计与实现中提出了一种实现方法,采用双通道,将Y通道与UV通道分别贴图。网上也有单通道经过一些转换再转换的方法,欢迎讨论。
首先我们探讨下YUV格式
android平台相机预览数据获取接口onPreviewFrame中默认获取的是YUV420sp格式,例如下图为8X4像素的YUV图像示意图
即首先将Y信号排列,然后UV数据分别交错排列。其中Y信号数组长度为width * height,UV信号长度为width * heght / 2,数组首元素位置起始于width * height。总长度为width * height * 1.5,相比于采用传统的rgb格式长度减少一半,因此常用语电视信号传输。
其中Y表示明亮度,也就是灰阶值。UV表示色度,是描述影响色彩及饱和度,用于指定像素颜色。因此,如果我们只使用Y通道,看到的就是原图的灰度图。
因为GPU并不会根据传入的纹理判断格式,所以我们可以将YUV数据作为RGB数据欺骗GPU,将Y通道与UV通道分成两个纹理传入shader,在shader中利用GPU的优势来进行快速转换。注意要使用两个不同的纹理单元,例如GL_TEXTURE0和GL_TEXTURE1,同样修改glUniform1i第二个参数
代码:
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, id_y);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
- glUniform1i(gvImageTextureY, 0);
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, id_uv);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, width/2, height/2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, data + width*height);
- glUniform1i(gvImageTextureUV, 1);
与直接使用RBGA数据不同,这里的参数采用的是GL_LUMINANCE,与GL_LUMINANCE_ALPHA,与GL_RGBA不同,GL_RGBA单独保存R、G、B、A四个数据,而GL_LUMINANCE将这四个数据合并成一个,因为这样1个Y就可以与1个RGBA对应。GL_LUMINANCE_ALPHA代表首先是亮度,然后是alpha值,这样我们就能将U值与V值分别取出。
之后通过shader将YUV格式转为RGB格式:
- precision mediump float;
- uniform sampler2D mGLUniformTexture;
- uniform sampler2D mGLUniformTexture1;
- varying highp vec2 textureCoordinate;
- const mat3 yuv2rgb = mat3(
- 1, 0, 1.2802,
- 1, -0.214821, -0.380589,
- 1, 2.127982, 0
- );
- void main() {
- vec3 yuv = vec3(
- 1.1643 * (texture2D(mGLUniformTexture, textureCoordinate).r - 0.0625),
- texture2D(mGLUniformTexture1, textureCoordinate).a - 0.5,
- texture2D(mGLUniformTexture1, textureCoordinate).r - 0.5
- );\
- vec3 rgb = yuv * yuv2rgb;
- gl_FragColor = vec4(rgb, 1);
- }
其中,texture2D(mGLUniformTexture, textureCoordinate).r即YUV中的Y数据,texture2D(mGLUniformTexture, textureCoordinate).a即YUV中的V数据,剩下一个就是U,经过矩阵公式转换后就是RGB数据,然后设置给gl_FragColor,OpenGL就可以正确的显示了
其余部分基本不变,也不再赘述
Android平台Camera实时滤镜实现方法探讨(三)--通过Shader实现YUV转换RBG的更多相关文章
- Android平台Camera实时滤镜实现方法探讨(十)--代码地址以及简单介绍(20160118更新)
简单做了个相机和图片编辑模块,时间原因非常多功能还没有做.尚有BUG,见谅,将在以后抽时间改动 代码地址 PS:请点个Star^-^ --------------------------------- ...
- Android平台Camera实时滤镜实现方法探讨(九)--磨皮算法探讨(一)
上一篇开头提到了一些可用于磨皮的去噪算法.以下我们实现这些算法而且观察效果,咱不考虑实时性的问题 本文首先探讨的首先是<基于局部均方差相关信息的图像去噪及其在实时磨皮美容算法中的应用> 该 ...
- Android平台Camera实时滤镜实现方法探讨(十一)--实时美颜滤镜
上一章完毕了对图片的磨皮处理.经过简单算法流程优化,能够达到非常快的速度.可是不能用于实时美颜.经实验,若採用仅仅处理Y信号的方案.半径极限大约是5-10,超过10则明显感受到卡顿.但对于1920X1 ...
- Unity3D之移植学习笔记:移植到Android平台
首先,我们需要一台已经配置好可以开发Android应用的计算机,这里我使用的是Windows系统+Eclipse+ADT的开发环境,当然也可以使用Android Studio或者使用Mac系统都可以. ...
- 【Android】Android Camera实时数据采集及通过MediaCodec硬编码编码数据的流程
吐槽: 其实常用流程都差不多,但是有时候还是会忘记某一步的详细用法,但是各位朋友请注意,官方已经不推荐Camera类的使用(现在是android.hardware.camera2),但无奈公司项目之前 ...
- Unity3D之移植学习笔记:移植到Android平台更好的方法
接上文,之前我们采用了直接将Unity项目导出为Eclipse项目来修改的方式,这种做法存在的一个最大的问题就是:每当Unity被修改之后,都需要重新导出,而每次导出的项目在Android平台方面的J ...
- 随笔之Android平台上的进程调度探讨
http://blog.csdn.net/innost/article/details/6940136 随笔之Android平台上的进程调度探讨 一由来 最近在翻阅MediaProvider的时候,突 ...
- 虹软人脸识别 - Android Camera实时人脸追踪画框适配
在使用虹软人脸识别Android SDK的过程中 ,预览时一般都需要绘制人脸框,但是和PC平台相机应用不同,在Android平台相机进行应用开发还需要考虑前后置相机切换.设备横竖屏切换等情况,因此在人 ...
- 高通Android平台硬件调试之Camera篇
之前一段时间有幸在高通android平台上调试2款camera sensor,一款是OV的5M YUV sensor,支持jpeg out,同时也支持AF,调试比较比较简单,因为别的项目已经在使用了, ...
随机推荐
- 【BZOJ】3300: [USACO2011 Feb]Best Parenthesis(模拟)
http://www.lydsy.com/JudgeOnline/problem.php?id=3300 这个细节太多QAQ 只要将所有的括号'('匹配到下一个')'然后dfs即可 简单吧,,, #i ...
- 浏览器配置工具.bat
在Web安装的ActiveX控件,默认安装在C:\WINDOWS\Downloaded Program Files目录下,但是有时候由于Internet Explorer的安全设置,会阻止Active ...
- Python_selenium封装一个浏览器引擎类
Python_selenium封装一个浏览器引擎类 现在我们在编写一个类,叫浏览器引擎类(此例为:启动浏览器),将文件名命名为browser.py,代码下面通过更改一个字符串的值,运用if语句判断和控 ...
- Python_selenium之处理Alert窗
Python_selenium之处理Alert窗 一.介绍 1. 介绍如何通过switch_to方法处理网页Alert窗口 2. 然后我们自己创建一个alert弹窗进行操作 二.测试脚本 1. 测试脚 ...
- Wex5循环某个div节点下的所有img标签,替换其src属性值
Model.prototype.newsDetailAfterRefresh = function(event){ var newsDiv = this.getElementByXid("n ...
- JStorm开发经验+运维经验总结
1.开发经验总结 ——12 Sep 2014 · 8 revisions 在jstorm中, spout中nextTuple和ack/fail运行在不同的线程中, 从而鼓励用户在nextTuple里 ...
- ORA-00257错误的解决办法
author: headsen chen date: 2018-04-17 11:12:39 notice:个人原创,转载请注明作者和出处,否则依法追击法律责任. 1,oracle数据库正常使用中 ...
- WM_MOUSEWHEEL消息
使用WM_MOUSEWHEEL 需要把CWnd设定为Focus ON_WM_MOUSEWHEEL( ) CWnd::OnMouseWheel afx_msg ...
- Java日志记录工具SLF4J介绍
SLF4J是什么 SLF4J是一个包装类,典型的facade模式的工具,对用户呈现统一的操作方式,兼容各种主流的日志记录框架,典型的有log4j/jdk logging/nop/simple/jaka ...
- Contos更换python版本
1.查看版本 #python -VPython 2.6.6 2.安装前准备,安装相关库#yum install gcc gcc-c++ autoconf automake#yum install op ...