将遮罩应用于图像
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
需要确保正确处理源图像和输出图像,否则最终可能会导致内存问题。
我需要通过遍历图像并为每个像素计算新值来手动将蒙版 (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
需要确保正确处理源图像和输出图像,否则最终可能会导致内存问题。