如果自定义一个OpenGL ES程序来处理图片,步骤如下:
- 初始化OpenGL ES环境,编译、链接Vertex Shader和Fragment Shader
- 缓存顶点、纹理坐标数据,传送图像数据到GPU
- 绘制图元到特定的帧缓存
- 在帧缓存中取出绘制的图像
其中GPUImageFilter
负责的是第一、二、三步,
GPUImageFrameBuffer
负责的是第四步。
GPUImageFilter
GPUImageFilter实现了 GPUImageInput
协议,可以输出纹理参与GPUImage的响应链,或者从响应链的接受纹理数据并处理图像
GPUImageFrameBuffer
管理纹理缓存格式、帧缓存的buffer
GPUImage
是一个开源的基于OpenGL ES
的图片视频处理框架,内置了非常多的常见滤镜效果,支持照相机和摄像头的实时滤镜,并且能够自定义图像滤镜
。
GPUImage采用链式方法来处理,通过addTarget方法添加对象到链中,处理完一个target,会把上一个环节处理好的数据图像传递到下一个target处理。
- GPUImageVideoCamera: 是
GPUImageOutput
的子类,摄像头用于实时拍摄视频,提供来自摄像头的图像数据作为源数据,一般是响应链的源头。- GPUImageStillCamera: 摄像头用于实时拍摄照片
- GPUImagePicture: 用于静态图像处理操作,可以是需要处理的静态图片,也可以是一张作为纹理使用的图片,调用它的
processImage方法
,进行图像滤镜处理- GPUImageMovie: 用于处理已经拍摄好的视频
- GPUImageFilter: 用来接收源图像,通过自定义的
Vertex Shader
和Fragment Shader
来渲染新的图像,并在绘制完成后通知响应链的下一个对象- GPUImageFilter的子类或者父类: 继承于
GPUImageOutput
,遵守GPUImageInput
协议,既可以流进数据,又可以流出数据- GPUImageView 和 GPUImageMovieWriter: 最终的输入目标,显示图片或者视频
混合滤镜
- 方式一:直接添加多个滤镜
GPUImagePicture *result = [[GPUImagePicture alloc] initWithImage: originalImage];
[result addTarget: filter1];
[result processImage];
[result addTarget: filter2];
[result processImage];
- 方式二:通过GPUImageFilterGroup,它是多个filter的集合
YUV
yuvConversionProgram: 将YUV颜色值转换成RGB值的程序(连接Vertex Shader和Fragment Shader)
美颜
磨皮
磨皮的本质实际上是模糊。而在图像处理领域,模糊就是将像素点的取值与周边的像素点取值相关联。而我们常见的高斯模糊 ,它的像素点取值则是由周边像素点求加权平均所得,而权重系数则是像素间的距离的高斯函数,大致关系是距离越小、权重系数越大。
如果单单使用高斯模糊来磨皮,得到的效果是不尽人意的。原因在于,高斯模糊只考虑了像素间的距离关系,没有考虑到像素值本身之间的差异。
举个例子来讲,头发与人脸分界处(颜色差异很大,黑色与人皮肤的颜色),如果采用高斯模糊则这个边缘也会模糊掉,这显然不是我们希望看到的。而双边滤波(Bilateral Filter) 则考虑到了颜色的差异,它的像素点取值也是周边像素点的加权平均,而且权重也是高斯函数。不同的是,这个权重不仅与像素间距离有关,还与像素值本身的差异有关,具体讲是,像素值差异越小,权重越大,也是这个特性让它具有了保持边缘的特性,因此它是一个很好的磨皮工具。