滤镜原理
滤镜说白了就是数字图像处理在视频播放、照片拍摄、后期上的具体应用
一个效果好的滤镜往往来自一个优秀的设计师,而不是一个深谙算法的程序员(当然提升效率还得靠图形程序员的帮助),所以设计师想要抢程序员饭碗真是太容易了。。。
例如,四邻域拉普拉斯算子对一幅图像进行卷积(锐化处理,突出边缘)的效果如下(转载自这里):
GPU加速方案
我们在使用滤镜时,往往希望能够实时看到效果,如果在使用相机预览或者播放视频的时候,能够直接看到叠加了滤镜的效果,那就更棒了。
这个需求就限制了每一帧数据的处理时间——不能大于16ms,如果实在慢的不行,怎么着也得有个24FPS吧(虽然24FPS肯定会看出卡顿的)
用GPU进行加速的原因是GPU最擅长做并行计算,GPU处理每个像素的时间可能会大于CPU,但是扛不住GPU核心数多呀(和CPU核心不是一个概念),这个并行计算是有一定限制的:
- 向GPU传递数据需要一定时间
- 算法必须符合或局部符合SIMD(Single Instruction Multiple Data,单指令多数据,可以近似理解成循环的每一步操作互不相关)
- 如果是传统GPGPU方案(例如OpenGL),算法需要进行大量改写以便适应渲染管线的表达方式
好在现在有CUDA和OpenCL(还有Vulkan、D3D什么的),在移动端OpenGL的版本3.0以上也快所占过半了(2017.01.29),大部分GPU都支持OpenCL(部分功能)
使用GPU进行加速,就是对于图像处理算法进行适当的改写,让GPU能够理解并符合GPU的执行方式(例如少用判断和循环等复杂控制结构,用矩阵简化运算等)
例如,我们想要把全景视频显示出来的界面变成黑白(灰度图),只需要这样修改之前我们写的fragment_shader
#extension GL_OES_EGL_image_external : require
precision mediump float;
varying vec2 vTextureCoord;
uniform samplerExternalOES sTexture;
void main() {
vec3 centralColor = texture2D(sTexture, vTextureCoord).rgb;
gl_FragColor = vec4(0.299*centralColor.r+0.587*centralColor.g+0.114*centralColor.b);
}
0.299,0.587,0.114是CRT中转灰度的模型(心理学公式),效果如下图所示: