Android平台美颜相机/Camera实时滤镜/视频编解码/影像后期/人脸技术探索——2.3 仿制Snow相机和FaceU的边框/小脸模式

本文介绍了如何在Android平台上仿制Snow和FaceU相机的小脸/边框模式。通过使用模糊算法(如FastBlur和GaussianBlur)并结合OpenGL进行GPU加速,实现相机画面的模糊效果。然后通过缩小图像并调整顶点坐标,创建类似边框的效果。文章提供了一种组合滤镜的方法,包括FastBlur和多次GaussianBlur,以实现平滑的模糊效果,并给出了实际运行在低端设备上的性能表现。
摘要由CSDN通过智能技术生成

Github项目地址

回到目录

在体验各种美颜相机时,我发现FaceU和Snow相机都带一个小脸模式(或者边框模式),像这样的效果:

这是Snow相机的:
这里写图片描述
这是FaceU的:
这里写图片描述

两个看上去并不一样,因为Snow相机的默认模式就是场景优化模式(感觉Snow相机的边框更漂亮一些),不过这哪里小脸啦,图片还是一样大的好吗???!!!!

本文的目标,就是仿制一个这样的边框效果。

解决方案

相信大家也能看出来,其实就是对场景做了一个模糊的效果(模糊的半径略大呀),然后再把画面缩小贴出来,个人感觉Snow相机的处理更漂亮一些,不过也可能跟前期处理有关,FaceU的模糊显得很一般,仔细看都能看到条纹。

模糊(Blur)算法选择

毫无疑问,Blur这种耗时的操作,我们肯定希望使用GPU来加速完成,常见的模糊算法(低通滤波)有FastBlur/BoxBlur,就是我们常见的图像卷积模糊以及在其上的各种优化姿势(例如积分图、线性可分等),以及高斯模糊,利用高斯分布(正太分布,正泰分布,正态分布。。终于打对了,好艰辛)来选择周围像素的权重。
对了,高斯模糊也是可以降维的,也就是两个维度的操作互不相关。
如果感兴趣,可以自己去找找模糊算法的相关资料。
较为复杂的FastBlur的代码如下(这里的卷积核不再是一个矩形,而是一个随机的球形卷积核)

precision mediump float;
varying vec2 vTextureCoord;
uniform sampler2D sTexture;

uniform vec3 iResolution;

vec2 Circle(float Start, float Points, float Point)
{
    float Rad = (3.141592 * 2.0 * (1.0 / Points)) * (Point + Start);
    return vec2(sin(Rad), cos(Rad));
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = fragCoord.xy;
    vec2 PixelOffset = 1.0 / iResolution.xy;

    float Start = 2.0 / 14.0;
    vec2 Scale = 0.66 * 4.0 * 2.0 * PixelOffset.xy;

    vec3 N0 = texture2D(sTexture, uv + Circle(Start, 14.0, 0.0) * Scale).rgb;
    vec3 N1 = texture2D(sTexture, uv + Circle(Start, 14.0, 1.0) * Scale).rgb;
    vec3 N2 = texture2D(sTexture, uv + Circle(Start, 14.0, 2.0) * Scale).rgb;
    vec3 N3 = texture2D(sTexture, uv + Circle(Start, 14.0, 3.0) * Scale).rgb;
    vec3 N4 = texture2D(sTexture, uv + Circle(Start, 14.0, 4.0) * Scale).rgb;
    vec3 N5 = texture2D(sTexture, uv + Circle(Start, 14.0, 5.0) * Scale).rgb;
    vec3 N6 = texture2D(sTexture, uv + Circle(Start, 14.0, 6.0) * Scale).rgb;
    vec3 N7 = texture2D(sTexture, uv + Circle(Start, 14.0, 7.0) * Scale).rgb;
    vec3 N8 = texture2D(sTexture, uv + Circle(Start, 14.0, 8.0) * Scale).rgb;
    vec3 N9 = texture2D(sTexture, uv + Circle(Start, 14.0, 9.0) * Scale).rgb;
    vec3 N10 = texture2D(sTexture, uv + Circle(Start, 14.0, 10.0) * Scale).rgb;
    vec3 N11 = texture2D(sTexture, uv + Circle(Start, 14.0, 11.0) * Scale).rgb;
    vec3 N12 = texture2D(sTexture, uv + Circle(Start, 14.0, 12.0) * Scale).rgb;
    vec3 N13 = texture2D(sTexture, uv + Circle(Start, 14.0, 13.0) * Scale).rgb;
    vec3 N14 = texture2D(sTexture, uv).rgb;

    float W = 1.0 / 15.0;

    vec3 color = vec3(0,0,0);

    color.rgb = 
        (N0 * W) +
        (N1 * W) +
        (N2 * W) +
        (N3 * W) +
        (N4 * W) +
        (N5 * W) +
        (N6 * W) +
        (N7 * W) +
        (N8 * W) +
        (N9 * W) +
        (N10 * W) +
        (N11 * W) +
        (N12 * W) +
        (N13 * W) +
        (N14 * W);
}

void main() {
    mainImage(gl_FragColor, vTextureCoord);
}

其实利用随机来做模糊是一个很棒的选择,但是有些低端移动GPU对于随机算法的支持非常烂,所以这就成为了一个备选方案。

But,高斯模糊和BoxBlur在半径较大的时候就歇菜了,因为是需要预处理(求和)的,如果我们使用OpenGL来做模糊半径一般都是3,那么在半径很大时就会出现很奇怪的重影效果。像GPUImage的高斯模糊在半径为20时的效果就成了这样(当然这也是和纹理大小以及GPU相关的):
模糊做成这样我也是醉了
这里写图片描述

怎么办呢,有两种解决方案:

  • 在GPUImage的IOS项目中,高斯模
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值