【Unity Shaders】抖音变身漫画 2

18 篇文章 1 订阅
6 篇文章 0 订阅

此篇文章只讨论图像处理部分,AI换脸暂不讨论。上图左边手机拍摄效果,右图是自己通过算法实现。

不同角度和亮度,不同参数的效果对比。

 

提亮图像

由于不同手机或图片的亮度信息不同,这里咱们先加了亮度调整,但是又不能平均加亮,这样会导至图片丢失很多细节,所以选择非线性提亮。

for(int i = 0; i < _Light; i++)
{
  col = pow(col, (1 - col/3.0));
}

非线性提亮方法有很多,大家下载工程后可自行发挥。

减少图像般色级别

提取象素明度信息,以明度为附加参数,减少色阶

fixed4  col    = tex2D(_MainTex, i.uv);
fixed  lum    = luminance(col);
col.rgb = floor((col.rgb * _quantizationLevels) + lum) / _quantizationLevels;

边缘提取

使用Sobel算子提取信息,拿到当前象素周围9个象素UV,然后采样得到象素信息,卷积拿到边缘信息。最后与边缘阀值比较,当前象素是否为边缘处理。

float  bottomLeftIntensity = tex2D(_MainTex, i.bLR.xy).r;
float  bottomRightIntensity = tex2D(_MainTex, i.bLR.zw).r;
​
float  topLeftIntensity = tex2D(_MainTex, i.tLR.xy).r;
float  topRightIntensity = tex2D(_MainTex, i.tLR.zw).r;
​
float  leftIntensity = tex2D(_MainTex, i.leftRight.xy).r;
float  rightIntensity = tex2D(_MainTex, i.leftRight.zw).r;
​
float  topIntensity = tex2D(_MainTex, i.topBottom.xy).r;
float  bottomIntensity = tex2D(_MainTex, i.topBottom.zw).r;
​
float  h = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity;
float  v = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity;
​
float  mag = length(float2(h, v));
float  thresholdTest = 1.0 - step(_threshold, mag);

图像混合

边缘信息后与减色阶后的图像混合得到最终颜色,漫画脸的颜色是固定的偏暖黄色,所以这里还要加一个颜色叠加,让最后的颜色看起来和脸部是相近色。

​float3  finalCol = col * thresholdTest;
finalCol = you * finalCol;
finalCol = 1 - (1 - finalCol) * (1 - _Color.rgb);
return float4(finalCol, 1);

C#代码部分

这个算法共两个Pass,提亮图像为一个Pass,减少色阶+边缘提取+图像混合为一个Pass,所以我们要先生成一个RenderTexture用来存提亮后的图像,然后以在这个图像上做相应处理。

void OnRenderImage(RenderTexture src, RenderTexture dest)
{
    if (material != null)
    {
        material.SetFloat("_quantizationLevels", quantizationLevels);
        material.SetFloat("_threshold", threshold);
        material.SetColor("_Color", col);
        material.SetFloat("_radius", radius);
        material.SetFloat("_Light", lighten);
​
        RenderTexture buffer0 = RenderTexture.GetTemporary(src.width, src.height, 0);
        buffer0.filterMode = FilterMode.Bilinear;
        Graphics.Blit(src, buffer0, material, 0);
​
​
        Graphics.Blit(buffer0, dest, material, 1);
        RenderTexture.ReleaseTemporary(buffer0);
    }
    else
    {
        Graphics.Blit(src, dest);
    }
}

 

工程代码 加 微信号:ITComputerGraph

更多精彩内容,关注公众号《IT木子李

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

linda012518

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值