程序不能对某些图像进行灰度化?
Program can't grayscale certain images?
我正在尝试创建一个程序,为我的计算机科学 class 在所选图像上应用灰度过滤器。
我在一个教程中找到了下面的代码,它演示了将图像中每个像素的R,G和B值替换为RGB值的平均值的灰度算法。
import java.io.File;
import java.io.IOException;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
public class Grayscale{
public static void main(String args[])throws IOException{
BufferedImage img = null;
File f = null;
//read image
try{
f = new File("D:\Image\Taj.jpg");
img = ImageIO.read(f);
}catch(IOException e){
System.out.println(e);
}
//get image width and height
int width = img.getWidth();
int height = img.getHeight();
//convert to grayscale
for(int y = 0; y < height; y++){
for(int x = 0; x < width; x++){
int p = img.getRGB(x,y);
int a = (p>>24)&0xff;
int r = (p>>16)&0xff;
int g = (p>>8)&0xff;
int b = p&0xff;
//calculate average
int avg = (r+g+b)/3;
//replace RGB value with avg
p = (a<<24) | (avg<<16) | (avg<<8) | avg;
img.setRGB(x, y, p);
}
}
//write image
try{
f = new File("D:\Image\Output.jpg");
ImageIO.write(img, "jpg", f);
}catch(IOException e){
System.out.println(e);
}
}//main() ends here
}//class ends here
问题是,程序没有在某些图像上正确应用灰度滤镜。例如,代码可以在 this image, creating a grayscale image 上正确应用过滤器。但是下面的一个图像
rainbow looks like this 应用了灰度滤镜。
为什么红色、绿色、蓝色和粉色在滤镜上方显示?我的理解是,当一个像素的R、G、B值相同时,应该创建一个灰色?
来自 BufferedImage.setRGB()
的 JavaDoc
"Sets a pixel in this BufferedImage to the specified RGB value. The pixel is assumed to be in the default RGB color model, TYPE_INT_ARGB, and default sRGB color space. For images with an IndexColorModel, the index with the nearest color is chosen."
要解决此问题,请创建一个具有所需颜色 space、与原始图像尺寸相同的新 BufferedImage,并将像素写入其中,而不是返回原始 BufferedImage。
BufferedImage targetImage = new BufferedImage(img.getWidth(),
img.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
改为将像素写入此图像...
targetImage.setRGB(x, y, p);
然后保存这张新图片..
ImageIO.write(targetImage, "jpg", f);
请注意,将彩色图像转换为灰度的更准确方法是将 RGB 像素转换为 YUV 颜色 space,然后使用亮度值,而不是 RGB 的平均值。这是因为 R G 和 B 的亮度权重不同。
我正在尝试创建一个程序,为我的计算机科学 class 在所选图像上应用灰度过滤器。 我在一个教程中找到了下面的代码,它演示了将图像中每个像素的R,G和B值替换为RGB值的平均值的灰度算法。
import java.io.File;
import java.io.IOException;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
public class Grayscale{
public static void main(String args[])throws IOException{
BufferedImage img = null;
File f = null;
//read image
try{
f = new File("D:\Image\Taj.jpg");
img = ImageIO.read(f);
}catch(IOException e){
System.out.println(e);
}
//get image width and height
int width = img.getWidth();
int height = img.getHeight();
//convert to grayscale
for(int y = 0; y < height; y++){
for(int x = 0; x < width; x++){
int p = img.getRGB(x,y);
int a = (p>>24)&0xff;
int r = (p>>16)&0xff;
int g = (p>>8)&0xff;
int b = p&0xff;
//calculate average
int avg = (r+g+b)/3;
//replace RGB value with avg
p = (a<<24) | (avg<<16) | (avg<<8) | avg;
img.setRGB(x, y, p);
}
}
//write image
try{
f = new File("D:\Image\Output.jpg");
ImageIO.write(img, "jpg", f);
}catch(IOException e){
System.out.println(e);
}
}//main() ends here
}//class ends here
问题是,程序没有在某些图像上正确应用灰度滤镜。例如,代码可以在 this image, creating a grayscale image 上正确应用过滤器。但是下面的一个图像 rainbow looks like this 应用了灰度滤镜。
为什么红色、绿色、蓝色和粉色在滤镜上方显示?我的理解是,当一个像素的R、G、B值相同时,应该创建一个灰色?
来自 BufferedImage.setRGB()
"Sets a pixel in this BufferedImage to the specified RGB value. The pixel is assumed to be in the default RGB color model, TYPE_INT_ARGB, and default sRGB color space. For images with an IndexColorModel, the index with the nearest color is chosen."
要解决此问题,请创建一个具有所需颜色 space、与原始图像尺寸相同的新 BufferedImage,并将像素写入其中,而不是返回原始 BufferedImage。
BufferedImage targetImage = new BufferedImage(img.getWidth(),
img.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
改为将像素写入此图像...
targetImage.setRGB(x, y, p);
然后保存这张新图片..
ImageIO.write(targetImage, "jpg", f);
请注意,将彩色图像转换为灰度的更准确方法是将 RGB 像素转换为 YUV 颜色 space,然后使用亮度值,而不是 RGB 的平均值。这是因为 R G 和 B 的亮度权重不同。