【问题标题】:Program can't grayscale certain images?程序不能对某些图像进行灰度化?
【发布时间】:2018-05-10 07:45:08
【问题描述】:

我正在尝试创建一个程序,为我的计算机科学课程在所选图像上应用灰度滤镜。 我在教程中找到了以下代码,它演示了灰度算法,其中图像中每个像素的 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 图像应用过滤器,创建grayscale image。但是下面的图像 rainbow 看起来像 this 应用了灰度滤镜。

为什么会显示红色、绿色、蓝色和粉红色,并带有过滤器?我的理解是,当一个像素的R、G、B值相同时,应该创建一个灰色?

【问题讨论】:

  • 我不确定算法有什么问题,但考虑过使用ColorConvertOp 代替吗? As demonstrated here
  • 您是否可以使用索引彩色图像而不是 rgb 图像?
  • @MadProgrammer 谢谢你的建议,我看看能不能用!但我仍然很好奇为什么算法不起作用。
  • @Shadowzee 如何检查它是否是索引彩色图像? (抱歉这个菜鸟问题)
  • @user9761831 我真的没有想法

标签: java image-manipulation grayscale


【解决方案1】:

来自BufferedImage.setRGB()的JavaDoc

"将此 BufferedImage 中的像素设置为指定的 RGB 值。假定该像素位于默认 RGB 颜色模型 TYPE_INT_ARGB 和默认 sRGB 颜色空间中。对于具有 IndexColorModel 的图像,具有选择最接近的颜色。”

要解决此问题,请创建一个具有所需色彩空间、与原始图像尺寸相同的新 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 颜色空间,然后使用亮度值,而不是 RGB 的平均值。这是因为 R G 和 B 的亮度加权不同。

【讨论】:

  • 当我创建新的图像类型 TYPE_3BYTE_BGR(与加载 JPG 时创建的类型相同)时,它似乎可以工作。 Jpeg 无论如何都没有 Alpha 通道。我本来希望它可以与其他类型一起使用。也许这与我们使用 setRGB 而不是使用绘图上下文有关。
猜你喜欢
  • 1970-01-01
  • 2013-04-15
  • 2013-01-03
  • 2021-02-07
  • 2012-12-12
  • 1970-01-01
  • 2019-04-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多