Unity 制作签名背景透明化效果,抠字效果

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_37608784/article/details/84450463

不知道公司是不是和我杠上了,进公司做的第一个项目是拍照,后面连续几个都有拍照功能,而且设计方案上还多加了签名的功能。

https://blog.csdn.net/weixin_37608784/article/details/82835865
上面网址介绍了我搜罗到的两种签名方法,可以用到项目中,方法一修改像素点,领导不满意,换了第二种方法,使用 LineRenderer 主相机照射 3D 场景和 UGUI 结合,达到签名效果。

本篇文章主要针对第二种方法进行优化。LineRenderer 这种方法本质是通过截图,并将截图叠加到照片上,再对照片进行二次截取进行保存。但是发现无论怎样截,都会把背景截进去,即主摄像机既能照到 LineRenderer 划出的线条(签名),也能找到线条后面的背景,签名那篇文章投机取巧将主相机上 Camera 组件上的 BackGround 修改为白色(这个也可以在线条后面加一个 Plane,只是确保大小在主相机的 Viewport Rect 在变成 (0,0,1,1)的时候能能把天空盒盖住(有点麻烦,直接修改天空盒就好)),还特意让美工在图片中间抠出一块透明的洞,让两个正好对上,造成假象。但效果是完成了。就是合成的时候把签名板背景图也给合成到照片上,像在照片上打了个补丁。
在这里插入图片描述

感觉一直是心里的一个梗,同时又因为接了个拍照项目,还有签名需求,而且甲方设计的相框在签名位置还有建筑线条,如果还是按照原来的方法就会把建筑线条盖住,索性找一找扣字效果的方法,即把背景图去掉。

不啰嗦了,文章参考了很多大神博客,都记不住了,在此感谢在博客上无私分享的前辈们。

先上效果图:

在这里插入图片描述

原理:

首先将图片灰度化处理,接着遍历所有像素,计算一下整张图的灰度的平均值(grayMean),图片中颜色较深部分,灰度值比较小,图片中颜色较浅部分,灰度值越大,加权平均值后总的平均值会比浅色部分的灰度值略低,比深色部分灰度值略高;然后再次遍历所有像素,并计算每个像素点的灰度,如果其灰度值比 grayMean 大,则将其 alpha 值设置为 0,即完全透明,否则不作处理。

代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class RemoveBorder : MonoBehaviour {

    public Image img;//原始签名图片
    Texture2D tex;
    public RawImage showImg;//处理后图片
    float grayMean;//整张图的平均灰度值
	// Use this for initialization
	void Start () {
        tex = img.mainTexture as Texture2D;
        showImg.texture=SpecialImgGray(tex) as Texture;
    }
    
    /// <summary>
    /// 拍照人脸彩色图做成灰度图
    /// </summary>
    Texture2D SpecialImgGray(Texture2D texSrc)
    {
        int width = texSrc.width;
        int height = texSrc.height;
        Texture2D texRec = new Texture2D(texSrc.width, texSrc.height);

       
        for (int i = 0; i < texSrc.width; i++)
        {
            for (int j = 0; j < texSrc.height; j++)
            {
                UnityEngine.Color c = texSrc.GetPixel(i, j);
                float r, g, b = 0;
                r = c.r;
                g = c.g;
                b = c.b;

                //灰度值计算公式
                grayMean += (r * 0.299f + g * 0.587f + b * 0.114f);
            }
        }
        //计算平均灰度
        grayMean = grayMean / (width * height);

        for (int i = 0; i < texSrc.width; i++)
        {
            for (int j = 0; j < texSrc.height; j++)
            {
                UnityEngine.Color c = texSrc.GetPixel(i, j);
                float r, g, b, Result = 0;
                r = c.r;
                g = c.g;
                b = c.b;
                
                //以加权平均值法  对图片进行灰度化处理
                //下面的 switch 语句可以用这一句 Result = (r * 0.299f + g * 0.587f + b * 0.114f);  代替。写这么多是因为之前做图片灰度化处理,下面的三种方法都可以,包括 case 2 中注释掉的那一句,提供大家一个思路
                int iType = 2;//1或者2都可以   3修改
                switch (iType)
                {
                    case 0://平均值法  
                        Result = ((r + g + b) / 3);
                        break;
                    case 1://最大值法  
                        Result = r > g ? r : g;
                        Result = Result > b ? Result : b;
                        break;
                    case 2://加权平均值法  
                        //Result = ((float)(0.7 * r) + (float)(0.2 * g) + (float)(0.1 * b));
                        Result = (r * 0.299f + g * 0.587f + b * 0.114f);
                        break;
                }

                //如果灰度值大于当前的平均灰度值,则将 alpha 设为 0
                if(Result>grayMean)
                {
                    texRec.SetPixel(i, j, new UnityEngine.Color(Result, Result, Result,0));
                }    
            }
        }
        texRec.Apply();
        return texRec;
    }
}

编辑器界面:

在这里插入图片描述

做两张图,一张 Image ,一张 RawImage,按照程序里的类型。你可以创建同一种类型。注意代码中类型的转换。Image上放你找到的签名图,注意:图片勾选 Read/Write Enabled ,图片可读写。

脚本挂到 Canvas 上,将两个物体拖拽到对应位置进行赋值。

运行即可。

猜你喜欢

转载自blog.csdn.net/weixin_37608784/article/details/84450463