java.awt.image.buffereImage使用自定义颜色空间将24位RGB图像转换为8位灰度

java.awt.image.buffereImage使用自定义颜色空间将24位RGB图像转换为8位灰度,java,image,image-processing,awt,jai,Java,Image,Image Processing,Awt,Jai,我想使用java.awt.image.buffereImage进行简单的颜色到灰度的转换。我是图像处理领域的初学者,所以如果我混淆了一些东西,请原谅 我的输入图像是一个RGB 24位图像(无alpha),我希望在输出上获得一个8位灰度buffereImage,这意味着我有这样一个类(为了清晰起见,省略了细节): 到目前为止,我已经成功尝试了两种转换方法,第一种是: private BufferedImageOp grayscaleConv = new ColorConv

我想使用
java.awt.image.buffereImage
进行简单的颜色到灰度的转换。我是图像处理领域的初学者,所以如果我混淆了一些东西,请原谅

我的输入图像是一个RGB 24位图像(无alpha),我希望在输出上获得一个8位灰度
buffereImage
,这意味着我有这样一个类(为了清晰起见,省略了细节):

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

    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);
            }
        }
    }
protectedvoid filter(){
WritableRaster raster=grayFrame.getRaster();
对于(int x=0;x>16)和0xff;
int g=(argb>>8)&0xff;
int b=(argb)&0xff;
int l=(int)(.299*r+.587*g+.114*b);
光栅设置样本(x,y,0,l);
}
}
}
第一种方法工作得更快,但生成的图像非常暗,这意味着我正在丢失带宽,这是不可接受的(在灰度和sRGB
ColorModel
之间使用了一些颜色转换映射,称为tosRGB8LUT,这对我来说不太合适,但我不确定,我只是假设使用了这些值)。第二种方法工作较慢,但效果非常好

是否有一种将这两者结合起来的方法,例如为
ColorConvertOp
使用自定义索引的
ColorSpace
?如果有,请给我举个例子好吗?


提前感谢。

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

有一个示例与第一个示例在一个小方面不同,
ColorConvertOp
的参数。请尝试以下操作:

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

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

以下是一种在某些情况下对我有效的解决方案

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


请记住,这种方法可能不会具有与标准亮度方法相同的质量级别,但是如果您正在寻找速度和质量之间的折衷方案,并且不想处理昂贵的浮点运算,那么它可能适合您。

这种建议的方法也会产生较暗的图像。我想知道是否有人有这样的想法ved解决了这个问题。@ecem可能与这个问题的原因相同:
protected void filter() {
   BufferedImageOp grayscaleConv = 
      new ColorConvertOp(colorFrame.getColorModel().getColorSpace(), 
                         grayFrame.getColorModel().getColorSpace(), null);
   grayscaleConv.filter(colorFrame, grayFrame);
}
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;
}