Bitmap.GetPixel 只为 R、G 和 B 返回 0
Bitmap.GetPixel only returning 0s for R, G and B
我正在使用 Image.FromFile
在控制台应用程序中加载图像。
之后,我将其转换为 Bitmap
以便能够使用 Bitmap.GetPixel()
方法。
令人惊讶的是,在遍历所有像素时,我从 GetPixel
得到的 R、G、B 都是 0,0,0。
为了确保从文件中正确读取图像,我添加了对 System.Windows.Forms
的引用,并将图像加载到 PictureBox
中以查看结果,图像很好看过。
原图:
以下是我如何加载图像并将其显示到 PictureBox
:
Bitmap img = (Bitmap)Image.FromFile("image.png");
PictureBox pb = new PictureBox
{
Image = img
};
Form frm = new Form
{
Controls = { pb }
};
frm.ShowDialog();
按原样显示图像:
之后,我得到的像素如下:
byte[] input = new byte[784];
for (int x = 0; x < 28; x++)
{
for (int y = 0; y < 28; y++)
{
Color color = img.GetPixel(x, y);
byte r = color.R;
byte g = color.G;
byte b = color.B;
Console.Write($"{color.R},{color.G},{color.B}|||");
input[x * 28 + y] = (byte)((((r + g + b) / 3)));
}
Console.WriteLine();
}
注意图片大小是28x28px,我试过其他图片也是一样的。
我期望结果显示真实的颜色值,因为我以前使用过该方法并且它工作得很好,但现在打印到控制台的所有结果都是零,我发现这很难理解。
编辑:
由于 PictureBox
显示的是真实图像表示,我尝试从 PictureBox.Image
中获取像素,例如:
Color color = ((Bitmap)pb.Image).GetPixel(x, y);
这也没有用,结果返回为零。
这可能是什么原因以及如何解决?
在您的图像中,所有像素的所有颜色通道 都是 0
,因此您的代码实际上工作正常。
而且大多数像素也有0
的alpha
,所以它们是透明的。有些是 semi-transparent、anti-aliased 像素,有些是完全不透明的。
透明或 semi-transprent 像素的地方,背景色会透出来。
如果您想识别真正的 non-transparent 黑色像素,您还需要测试 alpha 通道。
这是一个函数,它将创建像素颜色和给定背景颜色的复合颜色..:[=15=]
Color Composite(Color color, Color backcolor)
{
byte r = (byte)(((255 - color.A) * backcolor.R + color.R * color.A) / 256);
byte g = (byte)(((255 - color.A) * backcolor.G + color.G * color.A) / 256);
byte b = (byte)(((255 - color.A) * backcolor.B + color.B * color.A) / 256);
Color c2 = Color.FromArgb(255, r, g, b);
return c2;
}
如果您想要其中一个像素的亮度,您可以创建其颜色与白色的合成。但是,鉴于您拥有的图像,您也可以直接使用 color.A
..
我正在使用 Image.FromFile
在控制台应用程序中加载图像。
之后,我将其转换为 Bitmap
以便能够使用 Bitmap.GetPixel()
方法。
令人惊讶的是,在遍历所有像素时,我从 GetPixel
得到的 R、G、B 都是 0,0,0。
为了确保从文件中正确读取图像,我添加了对 System.Windows.Forms
的引用,并将图像加载到 PictureBox
中以查看结果,图像很好看过。
原图:
以下是我如何加载图像并将其显示到 PictureBox
:
Bitmap img = (Bitmap)Image.FromFile("image.png");
PictureBox pb = new PictureBox
{
Image = img
};
Form frm = new Form
{
Controls = { pb }
};
frm.ShowDialog();
按原样显示图像:
之后,我得到的像素如下:
byte[] input = new byte[784];
for (int x = 0; x < 28; x++)
{
for (int y = 0; y < 28; y++)
{
Color color = img.GetPixel(x, y);
byte r = color.R;
byte g = color.G;
byte b = color.B;
Console.Write($"{color.R},{color.G},{color.B}|||");
input[x * 28 + y] = (byte)((((r + g + b) / 3)));
}
Console.WriteLine();
}
注意图片大小是28x28px,我试过其他图片也是一样的。
我期望结果显示真实的颜色值,因为我以前使用过该方法并且它工作得很好,但现在打印到控制台的所有结果都是零,我发现这很难理解。
编辑:
由于 PictureBox
显示的是真实图像表示,我尝试从 PictureBox.Image
中获取像素,例如:
Color color = ((Bitmap)pb.Image).GetPixel(x, y);
这也没有用,结果返回为零。
这可能是什么原因以及如何解决?
在您的图像中,所有像素的所有颜色通道 都是 0
,因此您的代码实际上工作正常。
而且大多数像素也有0
的alpha
,所以它们是透明的。有些是 semi-transparent、anti-aliased 像素,有些是完全不透明的。
透明或 semi-transprent 像素的地方,背景色会透出来。
如果您想识别真正的 non-transparent 黑色像素,您还需要测试 alpha 通道。
这是一个函数,它将创建像素颜色和给定背景颜色的复合颜色..:[=15=]
Color Composite(Color color, Color backcolor)
{
byte r = (byte)(((255 - color.A) * backcolor.R + color.R * color.A) / 256);
byte g = (byte)(((255 - color.A) * backcolor.G + color.G * color.A) / 256);
byte b = (byte)(((255 - color.A) * backcolor.B + color.B * color.A) / 256);
Color c2 = Color.FromArgb(255, r, g, b);
return c2;
}
如果您想要其中一个像素的亮度,您可以创建其颜色与白色的合成。但是,鉴于您拥有的图像,您也可以直接使用 color.A
..