将遮罩应用于图像

Apply mask to image

我需要通过遍历图像并为每个像素计算新值来手动将蒙版 (3x3) 应用于图像。我的代码似乎有效,但有一个问题 - 新值可能不在 0 到 255 之间,它可以更高或更低。这样的值是不可接受的。现在我不知道如何正确解决它。

显然归一化到 0-255 会起作用,但在这里我需要对循环结束后已知的整组值进行归一化。这意味着我需要遍历整个图像两次。

您也可以评价我的代码,也许有些地方可以改进,也许尽管编译和创建处理过的图像它实际上不能正常工作。

        public Image<Rgba32> ApplyMask3x3(int[,] mask, Image<Rgba32> image)
        {
            Image<Rgba32> result = new Image<Rgba32>(image.Width, image.Height);

            for(int row = 0; row < image.Height; row++)
            {
                for(int col = 0; col < image.Width; col++)
                {
                    byte R = 0, G = 0, B = 0;

                    //temporary - forcefully throw new values to 0-255
                    int valR = ApplyMaskR3x3(col, row, image, mask); //code below
                    int valG = ApplyMaskG3x3(col, row, image, mask); //identical code as R but uses G attribute
                    int valB = ApplyMaskB3x3(col, row, image, mask); //identical code as R but uses B attribute
                    if (valR > 255) valR = 255;
                    if (valR < 0) valR = 0;
                    if (valG > 255) valG = 255;
                    if (valG < 0) valG = 0;
                    if (valB > 255) valB = 255;
                    if (valB < 0) valB = 0;

                    R = Convert.ToByte(valR);
                    G = Convert.ToByte(valG);
                    B = Convert.ToByte(valB); ;

                    result[col, row] = new Rgba32(R,G,B);
                }
            }

            return result;
        }
private int ApplyMaskR3x3(int col, int row, Image<Rgba32> image, int[,] mask)
        {
            int a, b, c;
            int d, e, f;
            int g, h, i;

            if (col == 0 || row == 0)
                a = 0;
            else
                a = image[col - 1, row - 1].R * mask[0, 0];

            if (row == 0)
                b = 0;
            else
                b = image[col, row - 1].R * mask[0, 1];

            if (row == 0 || col == image.Width - 1)
                c = 0;
            else
                c = image[col + 1, row - 1].R * mask[0, 2];


            if (col == 0)
                d = 0;
            else
                d = image[col - 1, row].R * mask[1, 0];

            e = image[col, row].R * mask[1, 1];

            if (col == image.Width - 1)
                f = 0;
            else
                f = image[col + 1, row].R * mask[1, 2];


            if (col == 0 || row == image.Height - 1)
                g = 0;
            else
                g = image[col - 1, row + 1].R * mask[2, 0];

            if (row == image.Height - 1)
                h = 0;
            else
                h = image[col, row + 1].R * mask[2, 1];

            if (col == image.Width - 1 || row == image.Height - 1)
                i = 0;
            else
                i = image[col + 1, row + 1].R * mask[2, 2];

            return a + b + c + d + e + f + g + h + i;
        }

您应该能够使用 ImageSharp

内置的 Filter 处理器

根据您的代码示例,您应该能够做到这一点

public Image<Rgba32> ApplyMask3x3(int[,] mask, Image<Rgba32> image)
{
    var matrix = new ColorMatrix(
        mask[0,0],
        mask[0,1],
        mask[0,2],
        mask[1,0],
        mask[1,1],
        mask[1,2],
        mask[2,0],
        mask[2,1],
        mask[2,2]
    );
    image.Mutate(x=>x.Filter(matrix));
    return image;
}

如果您确实需要第二张图片并且不想就地改变,请将 .Mutate() 替换为 .Clone()

如果您 Clone 需要确保正确处理源图像和输出图像,否则最终可能会导致内存问题。