2010-10-13 6 views
4

Je souhaite effectuer une conversion de couleur simple en niveaux de gris à l'aide de java.awt.image.BufferedImage. Je suis un débutant dans le domaine du traitement d'image, alors s'il vous plaît pardonnez si j'ai confondu quelque chose. Mon image d'entrée est une image RVB 24 bits (sans alpha), je voudrais obtenir une échelle de gris 8 bits BufferedImage sur la sortie, ce qui signifie que j'ai une classe comme celle-ci (détails omis pour plus de clarté):java.awt.image.BufferedImage Conversion de niveaux de gris RVB à 8 bits à 24 bits à l'aide de ColorSpace personnalisé

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

J'ai essayé avec succès 2 méthodes de conversion jusqu'à présent, tout d'abord être:

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

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

et le second étant:

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); 
      } 
     } 
    } 

La première méthode fonctionne beaucoup plus vite mais l'image produite est très sombre, ce qui signifie que je perds la bande passante ce qui est inacceptable (il y a un mappage de conversion de couleur entre les niveaux de gris et sRGB ColorModel appelé tosRGB8LUT qui ne fonctionne pas bien pour moi, pour autant que je sache mais je ne suis pas sûr, je suppose que ces valeurs sont utilisées). La deuxième méthode fonctionne plus lentement, mais l'effet est très agréable.

Existe-t-il une méthode pour combiner ces deux, par ex. en utilisant un index personnalisé ColorSpace pour ColorConvertOp? Si oui, pourriez-vous me donner un exemple?

Merci d'avance.

Répondre

2

Essayez de modifier votre seconde approche. Au lieu de travailler sur un seul pixel, récupérez un tableau de valeurs argb int, convertissez-le et rétablissez-le.

5

Il existe un exemple here qui diffère de votre premier exemple dans un petit aspect, les paramètres à ColorConvertOp. Essayez ceci:

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

Cette méthode suggérée produit également une image plus sombre. Je me demande si quelqu'un a résolu ce problème. – ecem

+0

@ecem peut-être c'est la même cause que dans cette question: http://stackoverflow.com/questions/15399653/image-conversion-to-grayscale-using-imagemagick-is-very-dark –

5
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; 
} 
0

La deuxième méthode est basée sur la luminance du pixel donc il obtient des résultats visuels plus favorables. Il pourrait être accéléré un peu en optimisant l'opération arithmétique à virgule flottante coûteuse lors du calcul de l en utilisant le tableau de recherche ou la table de hachage.

0

Voici une solution qui a fonctionné pour moi dans certaines situations. Prenez la hauteur de l'image y, la largeur de l'image x, la profondeur de couleur de l'image m et la taille du nombre entier n. Ne fonctionne que si (2^m)/(x * y * 2^n)> = 1. Conserver un nombre entier de n bits pour chaque canal de couleur lorsque vous traitez les valeurs d'échelle de gris initiales. Divisez chaque total par le (x * y) pour la valeur moyenne avr [canal] de chaque canal. Ajouter (192 - avr [canal]) à chaque pixel pour chaque canal. Gardez à l'esprit que cette approche n'aura probablement pas le même niveau de qualité que les approches de luminance standard, mais si vous recherchez un compromis entre rapidité et qualité, et que vous ne voulez pas faire face à des virgules flottantes coûteuses opérations, cela peut fonctionner pour vous.

Questions connexes