4

を使用して、単純なカラーからグレースケールへの変換を行いたいと考えていますjava.awt.image.BufferedImage。画像処理初心者ですので、見当違いでしたらご容赦ください。

私の入力画像は RGB 24 ビット画像 (アルファなし) です。出力で 8 ビット グレースケールを取得したいのですがBufferedImage、これは次のようなクラスを持っていることを意味します (明確にするために詳細は省略されています)。

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

私は今まで2つの変換方法をうまく試してきました。最初は次のとおりです。

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

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

そして2番目は:

    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 の間で使用される tosRGB8LUT と呼ばれる色変換マッピングがいくつかありColorModelますが、私にとってはうまく機能しません)。わかりますが、よくわかりません。それらの値が使用されていると思います)。2 番目の方法は動作が遅くなりますが、効果は非常に優れています。

これら2つを組み合わせる方法はありますか?カスタム インデックスColorSpaceを使用してColorConvertOp? はいの場合、例を教えてください。

前もって感謝します。

4

5 に答える 5

6
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;
}
于 2012-10-18T11:40:18.570 に答える
5

1 つの小さな側面である最初の例とは異なる例がここColorConvertOpにあります。これを試して:

protected void filter() {
   BufferedImageOp grayscaleConv = 
      new ColorConvertOp(colorFrame.getColorModel().getColorSpace(), 
                         grayFrame.getColorModel().getColorSpace(), null);
   grayscaleConv.filter(colorFrame, grayFrame);
}
于 2012-01-02T04:36:37.880 に答える
2

2 番目のアプローチを変更してみてください。単一のピクセルで作業する代わりに、argb int 値の配列を取得し、それを変換して元に戻します。

于 2011-02-06T21:57:32.543 に答える
0

2番目の方法はピクセルの輝度に基づいているため、より好ましい視覚的結果が得られます。ルックアップ配列またはハッシュテーブルを使用してlを計算するときに、コストのかかる浮動小数点演算を最適化することで、少し高速化できます。

于 2013-02-20T03:24:01.147 に答える
0

これは、いくつかの状況で私のために働いた解決策です。

画像の高さ y、画像の幅 x、画像の色深度 m、および整数ビット サイズ n を取ります。(2^m)/(x*y*2^n) >= 1 の場合にのみ機能します。初期グレー スケール値を処理するときに、各カラー チャネルの合計ビット整数を保持します。各合計を (x*y) で割り、各チャネルの平均値 avr[channel] を求めます。各チャネルの各ピクセルに (192 - avr[channel]) を追加します。

このアプローチは、おそらく標準の輝度アプローチと同じレベルの品質を持たないことに注意してください。ただし、速度と品質の妥協点を探していて、高価な浮動小数点演算を処理したくない場合は、あなたのために働きます。

于 2016-04-04T16:44:29.233 に答える