【问题标题】:java.awt.image.BufferedImage 24-bit RGB to 8-bit Grayscale conversion using custom ColorSpacejava.awt.image.BufferedImage 使用自定义 ColorSpace 将 24 位 RGB 转换为 8 位灰度
【发布时间】:2011-04-24 17:51:25
【问题描述】:

我想使用java.awt.image.BufferedImage 进行简单的颜色到灰度转换。我是图像处理领域的初学者,如有困惑请见谅。

我的输入图像是 RGB 24 位图像(无 alpha),我想在输出上获得 8 位灰度BufferedImage,这意味着我有一个这样的类(为清楚起见省略了详细信息) :

public class GrayscaleFilter {
    private BufferedImage colorFrame;
    private BufferedImage grayFrame = 
        new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);

到目前为止,我已经成功尝试了两种转换方法,首先是:

    private BufferedImageOp grayscaleConv = 
        new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);

    protected void filter() {
        grayscaleConv.filter(colorFrame, grayFrame);
    }

第二个是:

    protected void filter() {       
        WritableRaster raster = grayFrame.getRaster();

        for(int x = 0; x < raster.getWidth(); x++) {
            for(int y = 0; y < raster.getHeight(); y++){
                int argb = colorFrame.getRGB(x,y);
                int r = (argb >> 16) & 0xff;
                int g = (argb >>  8) & 0xff;
                int b = (argb      ) & 0xff;

                int l = (int) (.299 * r + .587 * g + .114 * b);
                raster.setSample(x, y, 0, l);
            }
        }
    }

第一种方法工作得更快,但生成的图像很暗,这意味着我正在失去带宽,这是不可接受的(在灰度和 sRGB ColorModel 之间使用了一些颜色转换映射,称为 tosRGB8LUT,效果不佳对我来说,据我所知,但我不确定,我只是假设使用了这些值)。第二种方法效果比较慢,但是效果很好。

有没有一种方法可以将这两者结合起来,例如。为ColorConvertOp 使用自定义索引ColorSpace?如果是的话,你能给我举个例子吗?

提前致谢。

【问题讨论】:

    标签: java image image-processing awt jai


    【解决方案1】:

    尝试修改您的第二种方法。无需处理单个像素,而是检索 argb int 值数组,将其转换并设置回来。

    【讨论】:

      【解决方案2】:

      有一个示例here 与您的第一个示例在一个小方面有所不同,即ColorConvertOp 的参数。试试这个:

      protected void filter() {
         BufferedImageOp grayscaleConv = 
            new ColorConvertOp(colorFrame.getColorModel().getColorSpace(), 
                               grayFrame.getColorModel().getColorSpace(), null);
         grayscaleConv.filter(colorFrame, grayFrame);
      }
      

      【讨论】:

      【解决方案3】:
      public BufferedImage getGrayScale(BufferedImage inputImage){
          BufferedImage img = new BufferedImage(inputImage.getWidth(), inputImage.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
          Graphics g = img.getGraphics();
          g.drawImage(inputImage, 0, 0, null);
          g.dispose();
          return img;
      }
      

      【讨论】:

        【解决方案4】:

        第二种方法是基于像素的亮度,因此可以获得更有利的视觉效果。在使用查找数组或哈希表计算 l 时,可以通过优化昂贵的浮点算术运算来加快速度。

        【讨论】:

          【解决方案5】:

          这是一个在某些情况下对我有用的解决方案。

          取图像高度y,图像宽度x,图像颜色深度m,整数位大小n。仅在 (2^m)/(x*y*2^n) >= 1 时有效。 在处理初始灰度值时,为每个颜色通道保留一个 n 位整数总数。每个通道的平均值 avr[channel] 将每个总数除以 (x*y)。将 (192 - avr[channel]) 添加到每个通道的每个像素。

          请记住,这种方法的质量水平可能与标准亮度方法不同,但如果您正在寻找速度和质量之间的折衷方案,并且不想处理昂贵的浮点运算,它可能对你有用。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-12-01
            • 1970-01-01
            • 1970-01-01
            • 2012-07-17
            • 2021-12-16
            • 1970-01-01
            • 1970-01-01
            • 2012-03-30
            相关资源
            最近更新 更多