Android平台美颜相机/Camera实时滤镜/视频编解码/影像后期/人脸技术探索——2.4 滤镜以及配套代码的制作方法

Github项目地址

好久没有更新了,不行不行,怎么可以太监呢(`⌒´メ)

滤镜结构

滤镜主要是对于图像的处理,关于一款滤镜的制作方法可以看这里

既然是图像处理,那么滤镜的操作就主要是:卷积、像素映射、坐标映射,反映到具体效果上,就是模糊锐化,覆盖层(贴纸等),RGB曲线调整,旋转缩放扭曲之类的。

嗯,就这么简单。

图像处理可以使用CPU来进行,但是由于我们每次只对图像的一小部分进行处理,因此可以考虑用并行的方式进行加速,这是典型的单指令(滤镜)多数据(图像),这个时候GPU就派上用场了,在移动平台上,我们可以使用最通用的OpenGL来利用GPU的计算性能。而我们需要付出的代价就是将之前的图像处理算法使用OpenGL能够理解的方式进行重写,着色器语言(OpenGL Shading Language)就是我们的工具。

让一款滤镜可以使用

我们知道了滤镜是怎么制作的,但是要如何让滤镜可以使用呢?例如实时用这个滤镜处理相机的预览结果并且显示出来。
以Android平台和OpenGL ES2.0+为例,我们可以发现主流滤镜的结构大概是这个样子:

  • 顶点着色器(vertex_shader)

  • 片元着色器(fragment_shader)

  • 颜色映射表/素材纹理(texture)

  • 对应控制代码

一个个来看吧。

顶点着色器(vertex_shader)

顶点着色器在一款滤镜中往往是不变的,一个标准的顶点着色器(图像,2D纹理)长这样:

attribute vec4 aPosition;
attribute vec4 aTextureCoord;
varying vec2 vTextureCoord;
void main() {
  gl_Position = aPosition;
  vTextureCoord = aTextureCoord.xy;
}

是不是异常简单?aPosition是顶点坐标,aTextureCoord是纹理坐标,vTextureCoord是用来向片元着色器传递纹理坐标用的,片元着色器会根据这个坐标对图片进行取样,然后进行处理,然后我们就完成了图像一个小区域的处理,GPU会自动对于纹理的所有小区域进行处理,完成滤镜的操作。

片元着色器(fragment_shader)

片元着色器是一款滤镜的核心,这其实就是我们的图像处理算法的描述,只不过我们现在用glsl的方式表述出来。
如果我们不需要对于图像进行任何处理,可以这样写:

precision mediump float;
varying vec2 vTextureCoord;
uniform sampler2D sTexture;
void main() {
    gl_FragColor=texture2D(sTexture, vTextureCoord);
}

是不是更简单?vTextureCoord是片元着色器传递过来的纹理坐标,sTexture就是我们的源图像了(相机预览、视频播放)。gl_FragColor是OpenGL的内置变量,他是一个vec4类型,代表当前片元的RGBA值,每个元素都是0-1的浮点数。

片元不一定是像素,他可能是相邻的好几个像素的集合,纹理的坐标是浮点数,而片元的中心是两个像素之间的中点。不过如果我们不使用glsl来做通用计算,而只是做图像处理的话,不需要特别在意这一点。

再分析一个高斯模糊的代码:

precision lowp float;
precision lowp int;
varying vec2 vTextureCoord;
uniform sampler2D sTexture;

varying vec2 blurCoordinates[5];

void main()
{
    vec4 original = texture2D(sTexture, vTextureCoord);
    lowp vec4 sum = vec4(0.0);
    sum += texture2D(sTexture, blurCoordinates[0]) * 0.204164;
    sum += texture2D(sTexture, blurCoordinates[1]) * 0.304005;
    sum += texture2D(sTexture, blurCoordinates[2]) * 0.304005;
    sum += texture2D(sTexture, blurCoordinates[3]) * 0.093913;
    sum += texture2D(sTexture, blurCoordinates[4]) * 0.093913;
    gl_FragColor = 
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值