高斯迷糊

二维高斯模糊比较费效率, 一般采用2次一维高斯模糊进行叠加,得到最终的效果图。

具体原理可以参加http://blog.csdn.net/zddblog/article/details/7450033

http://baike.baidu.com/link?url=Cz7VFPwxJ1N7zRNguVojw3iaPfFqb35nPrQ-sUwFYyiquokEZjytiZGSUtbct-XAnI_rD7ZPwrdkqzqqbbgDb_

 

在unity中做背景模糊的时候可以使用这种算法

private UITexture texture;

    private float[] gaussianTemplate;
    private int gaussianSize = 0;
    public Camera _mainCam;
    public Camera _uiCam;
    public int width = 256;  //待处理的原图的大小,越小越省内存
    public int height = 144; 
    public float sigma = 3.0f; //平滑层度
    // Use this for initialization
    void Start () {
        texture = GetComponent<UITexture>();
        
    }

    void GetGaussianTemplate()  //高斯模糊有效像素矩阵范围为 (+- 3sigma) 矩阵大小为 (6*sigma + 1) * (6*sigma + 1),利用2次一维高斯分布做叠加,加快运算
    {
        int size = Mathf.CeilToInt(3 * sigma) * 2 + 1;
        gaussianSize = size;
        gaussianTemplate = new float[size];
        float scale = -0.5f / (sigma * sigma);
        const float PI = 3.1415926f;
        float cons = 1/Mathf.Sqrt(-scale/PI);
        float sum = 0;
        int center = size / 2;
        for (int i = 0; i < size; i++)
        {
            int x = i - center;
            gaussianTemplate[i] = cons * Mathf.Exp(x * x * scale);
            sum += gaussianTemplate[i];
        }
        for (int i = 0; i < size; i++)   //归一化矩阵
        {
            gaussianTemplate[i] /= sum;
        }
    }

    // Update is called once per frame
    void Update () {
    
    }

    void OnGUI()
    {
        if (GUI.Button(new Rect(Screen.width/2,0,100,20),"GuassBlur"))
        {
            GetGaussianTemplate();
            StartCoroutine(UpdatePNG());
        }
    }

    IEnumerator UpdatePNG()
    {
        yield return new WaitForEndOfFrame();
        RenderTexture rt = new RenderTexture(width, height, 16, RenderTextureFormat.ARGB32);
        _mainCam.targetTexture = rt;
        _mainCam.Render();
        _uiCam.targetTexture = rt;
        _uiCam.Render();
        RenderTexture.active = rt;
        Texture2D _tex = new Texture2D(width, height, TextureFormat.RGB24, false);
        _tex.ReadPixels(new Rect(0, 0, width, height), 0, 0);
        _tex.Apply();
        _mainCam.targetTexture = null;
        _uiCam.targetTexture = null;
        RenderTexture.active = null;
        GuassBlur(_tex);
    }

    void GuassBlur(Texture2D tex)
    {
        Texture2D des = new Texture2D(tex.width, tex.height, TextureFormat.RGB24, false);
        Texture2D temp = new Texture2D(tex.width, tex.height, TextureFormat.RGB24, false);
        int center = gaussianSize / 2;
        for (int i = 0; i < tex.height; i++)
        {
            for (int j = 0; j < tex.width; j++)
            {
                Color acc = new Color(0, 0, 0);
                float sum = 0;
                for (int k = -center; k < center; k++)
                {
                    int pos = j + k;
                    if (pos >= 0 && pos < tex.width)
                    {
                        acc += tex.GetPixel(pos, i) * gaussianTemplate[k + center];
                        sum += gaussianTemplate[k + center];
                    }
                }
                temp.SetPixel(j, i, acc / sum);
            }
        }
        for (int i = 0; i < tex.width; i++)
        {
            for (int j = 0; j < tex.height; j++)
            {
                Color acc = new Color(0, 0, 0);
                float sum = 0;
                for (int k = -center; k < center; k++)
                {
                    int pos = j + k;
                    if (pos >= 0 && pos < tex.height)
                    {
                        acc += temp.GetPixel(i, pos) * gaussianTemplate[k + center];
                        sum += gaussianTemplate[k + center];
                    }
                }
                des.SetPixel(i, j, acc / sum);
            }
        }

        des.Apply();
        texture.mainTexture = des;      
    }

算法部分可以参见上面的网址,width和height用于内存控制和加快运算速度,sigma越大,越平滑,执行时间也越长。

posted @ 2015-03-13 17:30  yerongsc  阅读(424)  评论(0编辑  收藏  举报