鸟语天空
平滑滤波器
post by:追风剑情 2019-9-24 11:26

平滑滤波器又叫均值滤波器,可以使图片模糊,去噪。

示例:Unity实现

SmoothFilter.cs

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

// 平滑滤波器
public sealed class SmoothFilter {

    //定义滤波器模板
    private static int MAX_FILTER_X = 3;
    private static int FILTER_D = 1;
    private static float[] filter3x3 = new float[] {
        1, 1, 1,
        1, 1, 1,
        1, 1, 1
    };
    private static float[] filter = filter3x3;

    // 改变滤波器模板,n必须为奇数(如3、5、7、9、...)
    // n越大,图像越模糊
    public static void ChangeFilterTemplet(int n)
    {
        MAX_FILTER_X = n;
        FILTER_D = (n - 1) / 2;
        filter = new float[n*n];
        for (int i=0; i<filter.Length; i++)
            filter[i] = 1;
    }  

    public static Texture2D Apply(Texture2D raw)
    {
        int width = raw.width;
        int height = raw.height;
        Texture2D smoothTex = new Texture2D(width, height, TextureFormat.ARGB32, false);

        for (int y=0; y<height; y++)
        {
            for (int x=0; x<width; x++)
            {
                float r = 0, g = 0, b = 0;
                //计算模板对应像素区域的颜色之和
                for (int py=y-FILTER_D, fy=0; py <= y+FILTER_D; py++, fy++)
                {
                    for (int px=x-FILTER_D, fx=0; px <= x+FILTER_D; px++, fx++)
                    {
                        Color c = GetRawPixel(raw, px, py);
                        float f = GetFilterValue(fx, fy);
                        r += c.r * f;
                        g += c.g * f;
                        b += c.b * f;
                    }
                }
                //求颜色均值
                float fd = FilterDenominator;
                float mean_r = r / fd;
                float mean_g = g / fd;
                float mean_b = b / fd;
                Color mean_c = new Color(mean_r, mean_g, mean_b);
                SetSmoothPixel(smoothTex, x, y, mean_c);
            }
        }
        smoothTex.Apply();
        return smoothTex;
    }

    private static Color GetRawPixel(Texture2D raw, int x, int y)
    {
        if (x < 0 || y < 0 || x >= raw.width || y >= raw.height)
            return Color.black;
        return raw.GetPixel(x, y);
    }

    private static void SetSmoothPixel(Texture2D smoothTex, int x, int y, Color mean)
    {
        if (x < 0 || y < 0 || x >= smoothTex.width || y >= smoothTex.height)
            return;
        smoothTex.SetPixel(x, y, mean);
    }

    private static float GetFilterValue(int x, int y)
    {
        int i = y * MAX_FILTER_X + x;
        return filter[i];
    }

    // 模板各元素之和
    private static float FilterDenominator
    {
        get {
            float d = 0;
            for (int i=0; i<filter.Length; i++)
                d += filter[i];
            return d;
        }
    }
}


TestSmoothFilter.cs

using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// 测试脚本
public class TestSmoothFilter : MonoBehaviour 
{
    public Texture2D texture;
    public Texture2D smoothTexture;

    void Start () {
        SmoothFilter.ChangeFilterTemplet(3);
        smoothTexture = SmoothFilter.Apply(texture);
        SavePNG("D:/3x3.png", smoothTexture);

        SmoothFilter.ChangeFilterTemplet(5);
        smoothTexture = SmoothFilter.Apply(texture);
        SavePNG("D:/5x5.png", smoothTexture);

        SmoothFilter.ChangeFilterTemplet(7);
        smoothTexture = SmoothFilter.Apply(texture);
        SavePNG("D:/7x7.png", smoothTexture);

        SmoothFilter.ChangeFilterTemplet(9);
        smoothTexture = SmoothFilter.Apply(texture);
        SavePNG("D:/9x9.png", smoothTexture);

        SmoothFilter.ChangeFilterTemplet(15);
        smoothTexture = SmoothFilter.Apply(texture);
        SavePNG("D:/15x15.png", smoothTexture);
    }

    public void SavePNG(string filePath, Texture2D texture)
    {
        try
        {
            byte[] pngData = texture.EncodeToPNG();
            File.WriteAllBytes(filePath, pngData);
        }
        catch (Exception ex)
        {
            Debug.Log(ex.StackTrace);
        }
    }
}


运行测试

原图

head.png

3x3

3x3.png

5x5

5x5.png

7x7

7x7.png

9x9

9x9.png

15x15

15x15.png

评论:
发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容