将 RGB 像素转换为灰度会使暗像素呈现蓝色
Converting RGB pixels to greyscale makes dark pixels appear bluish
我目前正在试验 Java 中的图像,并尝试使用 BufferedImage class.
将 RGB 图像转换为灰度图像
我的想法是获取每个像素的RGB值并将它们设置为(R+G+B)/3:
BufferedImage image = ImageIO.read(new File(file));
int[] pixel;
int r, g, b;
for (int y = 0; y < image.getHeight(); y++)
{
for (int x = 0; x < image.getWidth(); x++)
{
pixel = image.getRaster().getPixel(x, y, new int[3]);
r = pixel[0];
g = pixel[1];
b = pixel[2];
int gr = (int)((r+g+b)/3);
String hex = Integer.toHexString(gr)+Integer.toHexString(gr)+Integer.toHexString(gr);
int i = Integer.parseInt(hex, 16);
image.setRGB(x, y, i);
}
}
ImageIO.write(image, "jpg", new File("im2.jpg"));
结果是这样的:
尽管这可能是将图像转换为灰度的最低效的方法,但我不知道为什么会这样。
我在这里错过了什么?
当十六进制值不是 2 位数字时会发生这种情况。例如。 Integer.toHexString(10)
returns "a"。
所以,例如,如果 r = 10
和 g = 10
和 b = 10
你会做 Integer.toHexString("aaa")
,这是相当蓝的(aa
= 170
) 带有淡淡的绿色 (a
= 10) 而没有红色。这种效果在图像的暗区会明显发生更多,并导致大部分是蓝色但有些偏绿的效果。
这是你图片的一小部分的放大图,显示了蓝色和轻微的绿色。
要修复它,请正确滚动数字。
image.setRGB(x, y, new Color(gr,gr,gr).getRGB());
而不是:
int gr = (int)((r+g+b)/3);
String hex = Integer.toHexString(gr)+Integer.toHexString(gr)+Integer.toHexString(gr);
int i = Integer.parseInt(hex, 16);
image.setRGB(x, y, i);
试试这个:
颜色 newColor = 新颜色(r+g+b,r+g+b,r+g+b);
image.setRGB(j,i,newColor.getRGB());
当您的灰度值低于 16 时,它将不再是 2 位十六进制数。所以你的十六进制字符串看起来像“444”而不是“040404”。这将导致蓝色。
你为什么不用
Color myColor = new Color(gr, gr, gr);
我目前正在试验 Java 中的图像,并尝试使用 BufferedImage class.
将 RGB 图像转换为灰度图像我的想法是获取每个像素的RGB值并将它们设置为(R+G+B)/3:
BufferedImage image = ImageIO.read(new File(file));
int[] pixel;
int r, g, b;
for (int y = 0; y < image.getHeight(); y++)
{
for (int x = 0; x < image.getWidth(); x++)
{
pixel = image.getRaster().getPixel(x, y, new int[3]);
r = pixel[0];
g = pixel[1];
b = pixel[2];
int gr = (int)((r+g+b)/3);
String hex = Integer.toHexString(gr)+Integer.toHexString(gr)+Integer.toHexString(gr);
int i = Integer.parseInt(hex, 16);
image.setRGB(x, y, i);
}
}
ImageIO.write(image, "jpg", new File("im2.jpg"));
结果是这样的:
尽管这可能是将图像转换为灰度的最低效的方法,但我不知道为什么会这样。 我在这里错过了什么?
当十六进制值不是 2 位数字时会发生这种情况。例如。 Integer.toHexString(10)
returns "a"。
所以,例如,如果 r = 10
和 g = 10
和 b = 10
你会做 Integer.toHexString("aaa")
,这是相当蓝的(aa
= 170
) 带有淡淡的绿色 (a
= 10) 而没有红色。这种效果在图像的暗区会明显发生更多,并导致大部分是蓝色但有些偏绿的效果。
这是你图片的一小部分的放大图,显示了蓝色和轻微的绿色。
要修复它,请正确滚动数字。
image.setRGB(x, y, new Color(gr,gr,gr).getRGB());
而不是:
int gr = (int)((r+g+b)/3);
String hex = Integer.toHexString(gr)+Integer.toHexString(gr)+Integer.toHexString(gr);
int i = Integer.parseInt(hex, 16);
image.setRGB(x, y, i);
试试这个:
颜色 newColor = 新颜色(r+g+b,r+g+b,r+g+b);
image.setRGB(j,i,newColor.getRGB());
当您的灰度值低于 16 时,它将不再是 2 位十六进制数。所以你的十六进制字符串看起来像“444”而不是“040404”。这将导致蓝色。
你为什么不用
Color myColor = new Color(gr, gr, gr);