图像处理入门——滤波

荒凉一梦 提交于 2020-12-05 02:40:02


模糊

图像模糊的方法可以将每个像素的rgb值用周围像素的加权平均值来代替。比如用周围的9个像素来计算加权平均值,权值可以用一个3x3的矩阵来表示:

| 1   2   1 |

| 2   4   2 |   *  (1/16)

| 1   2   1 |

中间的像素是要处理的像素,越靠近中间权值越大;所有权值的和为1。用平均值代替原像素的rgb值之后,每个像素于周围像素的差异程度变小了;该矩阵相当于一个二维的低通滤波器。下面是c#的代码

public Bitmap FilterBitmap(Bitmap bmp)
{
    // 创建如下3x3矩阵:
    //          | 1 2 1 |
    // (1/16) * | 2 4 2 |
    //          | 1 2 1 |
    double[,] core = new double[,] { { 1, 2, 1 }, { 2, 4, 2 }, { 1, 2, 1 } };
    int scale = 16;
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 3; j++)
            core[i, j] /= scale;

    Bitmap retBmp = new Bitmap(bmp.Width, bmp.Height);

    double r, g, b;
    int width = bmp.Width - 1;
    int height = bmp.Height - 1;

    // 循环处理第2行开始到倒数第2行;第2列开始到倒数第2列的像素,
    // 因为第最外面一圈的像素周围没有8个像素
    for (int y = 1; y < height; y++)
    {
        for (int x = 1; x < width; x++)
        {                    
            // 将周围8个像素的rgb加权平均值作为被处理像素的值
            r = g = b = 0;
            for (int j = -1; j <= 1; j++)
            {
                for (int i = -1; i <= 1; i++)
                {
                    Color pix = bmp.GetPixel(x + i, y + j);
                    r += core[i + 1, j + 1] * pix.R;
                    g += core[i + 1, j + 1] * pix.G;
                    b += core[i + 1, j + 1] * pix.B;
                }
            }                    
            // 确保rgb的值在0到255
            if (r < 0) r = 0; if (r > 255) r = 255;                                        
            if (b < 0) b = 0; if (b > 255) b = 255;                    
            if (g < 0) g = 0; if (g > 255) g = 255;                 

            retBmp.SetPixel(x, y, Color.FromArgb((int)r, (int)g, (int)b));
        }
    }
    return retBmp;
}

动态模糊或径向模糊等处理方法也是用加权平均值代替原像素的值,只是用于计算平均值的像素是一条曲线或射线上的像素而不是周围一圈的像素。

 

锐化

相对于模糊,锐化可以让图像看似更加清晰。方法是把每一个像素与周围像素的差异放大。同样可以用一个3x3矩阵来表示周围9个像素的权值,权值相加为1;与用于模糊的矩阵不同的是,用于锐化的矩阵中间像素的权值是正的,而周围的权值是负的。以下面的矩阵为例

| 0   –1    0 |

| –1   5   -1 |

| 0   –1    0 |

中间像素的rgb值先增大5倍,再与周围4个像素的rgb值做差,即:该像素 +(该像素-上面像素)+(该像素-下面像素)+(该像素-左边像素)+(该像素-右边像素)。结果是,如果周围像素相对该像素较暗,则差值为正,使得该像素更亮;反之如果周围像素相对较亮,则使得该像素更暗。该矩阵具有动态增加对比度的效果,相当于一个高通滤波器,

 

浮雕效果

浮雕效果与锐化的方法相似,稍不同的是矩阵中的权值相加为0,比如把上面矩阵中间的5改成4,用该像素与周围像素的差值代替该像素:

| 0    –1    0 |

| –1    4   -1 |

| 0    –1    0 |

不过一般的浮雕效果是有光照方向感的,比如东南方向(只与东南方向的像素对比):

| 0     0    0 |

| 0    2   -1 |

| 0   –1    0 |

效果是,如果该像素与周围相同,则该像素rgb的值变成0;如果该像素比周围像素亮,则差值为正;否则差值为负。但因为rgb的值只能是0~255,所以要把处理后的rgb值加上一个正的偏移量。

public Bitmap FilterBitmap(Bitmap bmp)
{
    // 创建如下3x3矩阵:
    // | 0  0   0 |
    // | 0  2  -1 |
    // | 0  -1  0 |
    int[,] core = new int[,] { { 0, 0, 0 }, { 0, 2, -1 }, { 0, -1, 0 } };
            
    // 偏移量
    int offset = 100;

    Bitmap retBmp = new Bitmap(bmp.Width, bmp.Height);
    int width = bmp.Width - 1;
    int height = bmp.Height - 1;            

    int r, g, b;
    for (int y = 1; y < height; y++)
    {
        for (int x = 1; x < width; x++)
        {
            r = g = b = 0;
            for (int j = -1; j <= 1; j++)
            {
                for (int i = -1; i <= 1; i++)
                {
                    Color pix = bmp.GetPixel(x + i, y + j);
                    r += core[i + 1, j + 1] * pix.R;
                    g += core[i + 1, j + 1] * pix.G;
                    b += core[i + 1, j + 1] * pix.B;
                }
            }

            // 加上偏移量
            r += offset;
            g += offset;
            b += offset;

            if (r < 0) r = 0; if (r > 255) r = 255;
            if (g < 0) g = 0; if (g > 255) g = 255;
            if (b < 0) b = 0; if (b > 255) b = 255;

            retBmp.SetPixel(x, y, Color.FromArgb(r, g, b));
        }
    }
    return retBmp;
}

锐化与浮雕处理可以应用于图像的边缘检测


以上主要参考《图像编程精髓——从开发自己的Photoshop开始》

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!