CodeS-SourceS
Rechercher un code, un tuto, une réponse

Traitement des images

Juillet 2017


Traitement des images


Ce tutoriel vous explique comment manipuler des BufferedImage, en appliquant des modifications sur les pixels, des convolutions, des filtres. Certains exemples sont fournis à la fin du tutoriel.



Charger une image


/* Chemin vers l'image à charger */
String pathImage = "D:\\image.jpg";

BufferedImage image;
try {
 image = ImageIO.read(new File(pathImage));
} 
catch (IOException e) {
 e.printStackTrace();
}

Enregistrer une image


try {
 ImageIO.write(image, "JPG", new File("image.jpg"));
} 
catch (IOException e) {
 e.printStackTrace();
}

Parcourir une image pixel par pixel


/* L'image à parcourir */
BufferedImage image = ImageIO.read(new File("D:\\image.jpg"))

int w = image.getWidth();
int h = image.getHeight();
for(int i=0; i<w; i++){
 for(int j=0; j<h; j++){
  /* Accéder au rgb pixel (i, j) */
  int rgb = image.getRGB(i,j);
 }
}

Récupérer la couleur d'un pixel


/* abscisse du pixel à récupérer */
int i=45;
/* ordonnée du pixel à récupérer */
int j=20;
/* L'image sur laquelle on travaille */
BufferedImage image = ImageIO.read(new File("D:\\image.jpg"))

/* Accéder au rgb pixel (i, j) */
int rgb = image.getRGB(i,j);
/* Création de la couleur associée au rgb */
Color couleur = new Color(rgb);

Modifier la couleur d'un pixel


/* abscisse du pixel à récupérer */
int i=45;
/* ordonnée du pixel à récupérer */
int j=20;
/* La couleur à affecter au pixel */
Color couleur = Color.BLUE;
/* L'image sur laquelle on travaille */
BufferedImage image = ImageIO.read(new File("D:\\image.jpg"))

/* Modification du pixel */
image.setRGB(i, j, couleur.getRGB());

Transformation affine des pixels


La classe RescaleOp permet d'appliquer une transformation affine sur les pixels d'une image.
RescaleOp(float scaleFactor, float offset, RenderingHints hints)
  • red=scaleFactor*red+offset
  • green=scaleFactor*green+offset
  • blue=scaleFactor*blue+offset


RescaleOp(float[] scaleFactor, float[] offset, RenderingHints hints)
  • red=scaleFactor[0]*red+offset[0]
  • green=scaleFactor[1]*green+offset[1]
  • blue=scaleFactor[2]*blue+offset[2]
  • alpha=scaleFactor[3]*alpha+offset[3]


Pour l'utiliser :
/* L'image sur laquelle on travaille */
BufferedImage image = ImageIO.read(new File("D:\\image.jpg"))

/* Création de la transformation */
RescaleOp rop = new RescaleOp(1.0f, 5.0f, null);

/* Application de la transformation */
BufferedImage resultat=op.filter(image, null)

Appliquer un filtre (convolution)

Qu'est ce qu'une convolution


La convolution consiste à recalculer la valeur d'un pixel donné d'une image de départ en se basant sur la valeur du pixel lui-même et sur la valeur des pixels environnants le pixel à recalculer.

Une convolutions est associée à un noyau (kernel qui est une matrice qui définit les pondérations à prendre en compte pour calculer le produit de convolution).

Le schéma suivant illustre la façon dont la valeur d'un pixel est calculée lorsqu'on applique une convolution.

  • La matrice de gauche est l'image source
  • La matrice au centre est le noyau
  • Le résultat est la valeur du pixel central

Définir une convolution


Pour définir une convolution, nous allons instancier la classe ConvoleOp en lui précisant le noyau de notre convolution : la classe Kernel nous permet de définir le noyau.

Définir le noyau


Pour définir le noyau, nous utilisons le constructeur : Kernel(int width, int height, float[] data)
  • width est le nombre de colonnes du noyau
  • height est le nombre de lignes du noyau
  • data est le tableau contenant les pondérations listées en ligne.


Par exemple, pour définir le noyau suivant :

On utilise :
new Kernel(3, 2, new float[]{1, 2, 3, 4, 5, 6})

Définition et application de la convolution


/* L'image sur laquelle on travaille */
BufferedImage image = ImageIO.read(new File("D:\\image.jpg"))

/* Définition du noyau */
Kernel kernel = new Kernel(3, 2, new float[]{1, 2, 3, 4, 5, 6};

/* Création de la convolution associée */
ConvolveOp convolution = new ConvolveOp(kernel);

/* Application de la convolution à l'image */
BufferedImage resultat=convolution.filter(image, null);

Détection du contour (Convolution de Sobel)


Le Filtre de sobel consiste à appliquer deux convolutions consécutives qui ont pour matrices :


Ce filtre permet de détecter les contours d'une image comme ceci :


import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;


public class Sobel {

 public static void main(String[] args) {
  BufferedImage source=null;
  try {
   source = ImageIO.read(new File("D:\\exemple.jpg"));
  }
  catch (IOException e) {
   e.printStackTrace();
  }
  
  /* Définition de la première convolution */
  Kernel kernel1 = new Kernel(3, 3, new float[]{1f, 0f, -1f, 2f, 0f, -2f, 1f, 0f, -1f});
  ConvolveOp convolution1 = new ConvolveOp(kernel1);
  BufferedImage resultatIntermediaire = convolution1.filter(source, null);
  
  /* Définition de la deuxième convolution */
  Kernel kernel2 = new Kernel(3, 3, new float[]{1f, 2f, 1f, 0f, 0f, 0f, -1f, -2f, -1f});
  ConvolveOp convolution2 = new ConvolveOp(kernel2);
  BufferedImage resultat = convolution2.filter(resultatIntermediaire, null);
  
  /* Ecriture du résultat */
  try {
   ImageIO.write(resultat, "JPG", new File("D:\\resultat.jpg"));
  } 
  catch (IOException e) {
   e.printStackTrace();
  }
 }

}

Lissage par convolution


Le lissage par convolution consiste à appliquer un filtre particulier de dimensions 5*5 qui permet d'atténuer les contours. Cette matrice est la suivante :
new float[]{ 4/1344f, 18/1344f, 19/1344f, 18/1344f, 4/1344f, 18/1344f, 80/1344f, 132/1344f, 80/1344f, 18/1344f, 29/1344f, 132/1344f, 218/1344f, 132/1344f, 29/1344f, 18/1344f, 80/1344f, 132/1344f, 80/1344f, 18/1344f, 4/1344f, 18/1344f, 29/1344f, 18/1344f, 4/1344f}


Le résultat est le suivant :


import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;


public class Lissage {

 public static void main(String[] args) {
  BufferedImage source=null;
  try {
   source = ImageIO.read(new File("D:\\exemple.jpg"));
  }
  catch (IOException e) {
   e.printStackTrace();
  }
  
  /* Définition de la convolution */
  Kernel kernel1 = new Kernel(5, 5, new float[]{ 4/1344f, 18/1344f, 19/1344f, 18/1344f, 4/1344f, 18/1344f, 80/1344f, 132/1344f, 80/1344f, 18/1344f, 29/1344f, 132/1344f, 218/1344f, 132/1344f, 29/1344f, 18/1344f, 80/1344f, 132/1344f, 80/1344f, 18/1344f, 4/1344f, 18/1344f, 29/1344f, 18/1344f, 4/1344f});
  ConvolveOp convolution = new ConvolveOp(kernel1);
  BufferedImage resultat = convolution.filter(source, null);
  
  /* Ecriture du résultat */
  try {
   ImageIO.write(resultat, "JPG", new File("D:\\resultat.jpg"));
  } 
  catch (IOException e) {
   e.printStackTrace();
  }
 }

}

Inversion des couleurs




Pour inverser les couleurs, on effectuer un traitement pixel par pixel :
  • red=255-red
  • green=255-green
  • blue=255-blue


import java.awt.image.BufferedImage;
import java.awt.image.RescaleOp;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;


public class InversionCouleur {

 public static void main(String[] args) {
  BufferedImage source=null;
  try {
   source = ImageIO.read(new File("D:\\exemple.jpg"));
  }
  catch (IOException e) {
   e.printStackTrace();
  }
  
  /* Définition de la transformation */
  RescaleOp op = new RescaleOp(-1.0f, 255f, null);
  BufferedImage resultat = op.filter(source, null);
  
  /* Ecriture du résultat */
  try {
   ImageIO.write(resultat, "JPG", new File("D:\\resultat.jpg"));
  } 
  catch (IOException e) {
   e.printStackTrace();
  }
 }

}

Niveaux de gris




Pour passer une image en niveau de gris, on utilise la classe ColorConvertOp :
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.awt.image.RescaleOp;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;


public class NiveauGris {

 public static void main(String[] args) {
  BufferedImage source=null;
  try {
   source = ImageIO.read(new File("D:\\exemple.jpg"));
  }
  catch (IOException e) {
   e.printStackTrace();
  }
  
  /* Définition de la transformation */
  ColorConvertOp op = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
  BufferedImage resultat = op.filter(source, null);
  
  /* Ecriture du résultat */
  try {
   ImageIO.write(resultat, "JPG", new File("D:\\resultat.jpg"));
  } 
  catch (IOException e) {
   e.printStackTrace();
  }
 }

}


Sepia




La passage d'une image en sepia est une transformation non affine pixel par pixel, il n'existe pas de classe permettant de définir ce genre de transformation.

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;


public class Sepia {

 public static void main(String[] args) {
  BufferedImage source=null;
  try {
   source = ImageIO.read(new File("D:\\exemple.jpg"));
  }
  catch (IOException e) {
   e.printStackTrace();
  }

  int w = source.getWidth();
  int h = source.getHeight();
  for(int i=0; i<w; i++){
   for(int j=0; j<h; j++){
    Color c = new Color(source.getRGB(i, j));
    int outputRed = (int) Math.min(255, ((c.getRed() * 0.393f) + (c.getGreen() *0.769f) + (c.getBlue() * 0.189f)));
    int outputGreen = (int) Math.min(255, ((c.getRed() * 0.349f) + (c.getGreen() *0.686f) + (c.getBlue() * 0.168f)));
    int outputBlue = (int) Math.min(255, ((c.getRed() * 0.272f) + (c.getGreen() * 0.534f) + (c.getBlue() *  0.131f)));
    source.setRGB(i,j,new Color(outputRed, outputGreen, outputBlue).getRGB());
   }
  }
  
  /* Ecriture du résultat */
  try {
   ImageIO.write(source, "JPG", new File("D:\\resultat.jpg"));
  } 
  catch (IOException e) {
   e.printStackTrace();
  }
 }

}

A voir également

Publié par cs_Julien39.
Ce document intitulé «  Traitement des images  » issu de CodeS-SourceS (codes-sources.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.
Ajouter un commentaire

Commentaires

Donnez votre avis
Gestion des Thread
Lancement d'un commande avec Runtime.exec()