Débruitage d’images par Analyse en Composantes Principales (ACP)

Projet Java implémentant une méthode de débruitage basée sur la décomposition en composantes principales des patches d’image. Interface JavaFX, calcul matriciel via Apache Commons Math, utilitaires image et pipeline expérimentaux contenus sous src/.

But et approche

L’objectif est de concevoir et d’implémenter un algorithme de débruitage d’images reposant sur l’Analyse en Composantes Principales (ACP / PCA). L’idée centrale : découper l’image en petits patchs redondants, construire une matrice où chaque ligne représente un patch, extraire les axes principaux (vecteurs propres) de la covariance, projeter chaque patch sur un sous-espace de faible dimension puis reconstruire l’image à partir des contributions retenues.

Le pipeline est conçu pour être expérimental et pédagogique : paramètres (taille de patch, nombre de composantes, méthode de seuillage) sont ajustables via l’interface JavaFX et le code.

Stack technique & artefacts

Stack

  • Java (JDK 11+ / 17+ compatible)
  • JavaFX (interface graphique)
  • Apache Commons Math 3.6.1 — calculs matriciels & décomposition
  • Makefile (compilation / packaging)
  • Bibliothèque locale : lib/commons-math3-3.6.1.jar et jars JavaFX

Contenu du dépôt

L’application est organisée de manière modulaire : src/core (traitement d’image et algorithmes ACP), src/gui (interface JavaFX) et src/main (lancement & console).

Voir README complet

Algorithme : pipeline détaillé

1. Prétraitement

- Chargement de l’image via ImageIO (utilisé à plusieurs endroits ; on centralise la lecture/écriture dans Image).
- Conversion RGB → niveaux de gris (luminosité) si nécessaire ; l’algorithme opère sur des valeurs scalaires par pixel.

2. Découpage en patches

- Les patches sont des blocs carrés extraits de l’image : méthodes utilitaires dans core/Image.java fournissent decoupeImage, decoupeImageEnQuatre, decoupeImageSelonCarreParfait selon le besoin expérimental.
- Chaque patch est encapsulé dans core/Patch.java, et la collection de patches est manipulée via PatchCollection.java.

- Plusieurs stratégies d’extraction sont supportées : tirage aléatoire de patches, partition régulière (grille) ou découpage en sous-blocs égaux. L’implémentation convertit ensuite chaque patch en vecteur (ligne de la matrice de données).

3. Construction de la matrice & centrage

- On construit une matrice X ∈ R^{N×p}N est le nombre de patches et p = s × s la dimension d’un patch aplati.
- Le centrage (soustraction de la moyenne par colonne) est effectué via PatchCollection.moyCov(...) qui renvoie la moyenne et la matrice de covariance.

4. Calcul de l’ACP (vecteurs propres)

- La décomposition spectrale (EigenDecomposition) est effectuée via Apache Commons Math : méthode OutilsMathematiques.calculerVecteursPropres(RealMatrix).
- Les vecteurs propres sont triés par valeur propre décroissante pour capturer d’abord la variance la plus importante.

5. Projection & seuillage

- Chaque patch centré est projeté sur la base des vecteurs propres : OutilsMathematiques.projeterContributions calcule les contributions (coefficients α_k).
- Optionnellement, on applique un seuillage sur ces coefficients (méthodes implémentées dans Patch / Critere) : seuillage dur ou doux, avec critères SV (VisuShrink) ou BayesShrink.

6. Reconstruction

- Après seuillage, on reconstruit chaque patch : somme du vecteur moyen + combinaison linéaire des vecteurs de base pondérés par les coefficients seuillés (implémenté dans Image.reconctructionSeuillage ; attention: accumulation des contributions correctement implémentée pour additionner et non écraser les valeurs).
- Les patches reconstruits sont ensuite remis en place dans l’image finale (PatchCollection.reconstructPatchs2 ou Image.reconstituerImage).

7. Post-traitement & métriques

- Calcul du PSNR (Peak Signal-to-Noise Ratio) et/ou MSE entre l’image d’origine et l’image débruitée pour évaluer la qualité.
- Affichage des courbes de variance expliquée (somme cumulée des valeurs propres) pour aider le choix du nombre de composantes retenues.

Schéma détaillé du pipeline ACP
Pipeline détaillé : extraction → ACP → seuillage → reconstruction.

Arborescence du projet

Implémentation : description des classes clés

core/Image.java

- Lecture/écriture d’images, conversion en matrice pixels, fonctions d’ajout de bruit (gaussien), découpage en imagettes (patchs) et reconstitution.
- Méthodes notables : decoupeImage(...), decoupeImageEnQuatre(...), decoupeImageSelonCarreParfait(...), reconstituerImage(...), imageDEN(...), imageDENlocale(...), reconctructionSeuillage(...).

- Gestion des imagettes : la classe interne Image.Imagette encapsule la sous-image et la position (x,y) dans l’image source.

core/Patch.java

- Représente un patch sous forme d’un vecteur (tableau de doubles) avec getters/setters pour valeurs de pixels et opérations de seuillage (dur/doux).
- Les méthodes de seuillage sont appliquées sur les coefficients α, et la classe fournit des utilitaires pour manipuler et convertir les données pixels.

core/PatchCollection.java

- Container pour une collection de Patch et leurs positions. Fournit :

  • extractPatches(BufferedImage, patchSize) — extraction de patches
  • moyCov(PatchCollection) — calcul du vecteur moyen et de la matrice de covariance
  • reconstructPatchs2(...) — algorithme pour assembler les patches en image finale
  • Accesseurs : getPatches(), getPatchPositions()

core/OutilsMathematiques.java

- Fonctions numériques : conversion collection ↔ matrice, calcul des vecteurs propres via EigenDecomposition, tri des vecteurs propres, conversion de matrice en PatchCollection et projection des contributions (projeterContributions).

- Méthode importante : calculerVecteursPropres(RealMatrix) qui encapsule l'appel à la décomposition spectrale d'Apache Commons Math et trie les composantes par valeur propre.

core/Critere.java

- Implémente des critères de seuillage / détermination du seuil lambda : par exemple seuilVisuShrink (VisuShrink) et seuilBayesShrink (BayesShrink). Ces méthodes servent à définir la force du seuillage appliqué aux coefficients projetés.

src/gui/* (JavaFX)

- Interface organisée en écrans : Accueil (point d'entrée graphique), ChoixImage (sélection d'image), ChoixParametres (taille patchs, sigma, méthode de seuillage), Resultat (visualisation avant/après et métriques).
- Les actions utilisateur déclenchent le pipeline via des appels aux classes core (ex : lancer Image.imageDEN).

src/main/Main.java & Console.java

- Main lance l’interface JavaFX (classe Application) ; Console permet un mode non-GUI (scriptable) pour tests batch.

Optimisations, limites numériques et pistes d’amélioration

Complexité & mémoire

- Matrice de patches : la mémoire augmente avec N × p (N = nb patches, p = s*s). Pour images grandes ou patchs grands, la matrice peut devenir volumineuse. - Approche : réduire N (sous-échantillonnage), utiliser représentation en float ou traitements par blocs, ou effectuer une ACP économe (SVD tronqué, méthodes incrémentales).

Performances & parallélisme

- Les étapes d'extraction de patches et de projection sont massivement parallélisables. On peut paralléliser :

  • l'extraction et conversion des patches (threads pour sous-ensembles de l'image)
  • la projection des patches (ExecutorService)

- Pour une version JDK moderne, utiliser ForkJoinPool ou les Streams parallèles avec attention sur la création d'objets temporaires.

Améliorations algorithmiques

  • Utiliser SVD tronqué (algorithmes itératifs) pour éviter la factorisation complète quand seules k premières composantes sont nécessaires.
  • Tester des méthodes non-linéaires (ex. RPCA, NMF) pour différents types de bruit.
  • Ajouter un pipeline de validation croisée pour choisir automatiquement k (nombre de composantes).

Robustesse & qualité

- Ajout de contrôles sur les tailles de patch et sur le recouvrement pour éviter les erreurs d’indice dans getSubimage.
- Logging centralisé (java.util.logging ou SLF4J) pour tracer les erreurs d’E/S et calculs numériques.

Utilisation — exemples

Mode GUI (JavaFX)

  1. Lancer l’application : java -jar debruitage.jar
    ou directement via le Makefile :
    • make → compile et génère les JAR dans dist/
    • make run → lance l’application avec les bons modules JavaFX
  2. Choisir une image depuis data/ (ex. lena.jpg)
  3. Régler : taille de patch (ex. 7), nombre de composantes k, sigma estimé, méthode de seuillage (Dur/Doux), critère (SV/Bayes)
  4. Lancer le traitement et visualiser le résultat dans l’onglet Resultat — téléchargeable en JPG

Mesures

Le programme calcule et affiche :

  • PSNR avant/après
  • MSE
  • Variance expliquée par k composantes (courbe cumulative)

Utilisation du Makefile

  • make → compile les sources et génère GM1Groupe9_Used.jar et GM1Groupe1_Executable.jar dans dist/
  • make run → exécute directement l’application (équivalent à java -jar dist/GM1Groupe9_Used.jar)
  • make archive → crée une archive complète du projet (GM1Groupe9_Archive.jar)
  • make clean → nettoie les répertoires bin/ et dist/ tout en restaurant les images de test dans data/

Annexes techniques & extraits de code

Structure de données (Patch)

public class Patch {
    private double[] pixels; // dimension p = s*s
    // getPixel(i), setPixel(i,val)
    // seuillageDur(index, lambda)
    // seuillageDoux(index, lambda)
}
          

Extrait : calcul de la projection (schéma)

# pseudo-code (inspiré de OutilsMathematiques.projeterContributions)
for each basis vector u_i:
    for each centered patch v_k:
        alpha[k][i] = dot(u_i, v_k)
# alpha : contributions (N x p)
# reconstruction: v_k_hat = mean + sum_i alpha[k][i] * u_i
          

Critères de seuillage

- seuilVisuShrink : règle basée sur bruit et taille d'image (valeur scalaire λ calculée, méthode classique en ondelettes).
- seuilBayesShrink : estimation statistique bayésienne du seuil en fonction de la variance du bruit et de la variance estimée du signal.

Conclusion et perspectives

Le projet est un cadre flexible pour expérimenter des méthodes de débruitage basées sur des décompositions linéaires. À l’état actuel, la version JavaFX propose une interface complète et un pipeline reproductible ; les axes prioritaires d’amélioration sont :

  • Optimisation mémoire (SVD tronqué, traitements par blocs)
  • Parallélisation des étapes d’extraction/projection
  • Ajout d’un module d’évaluation automatisée (benchmarks, PSNR sur datasets standards)
  • Ajout d’un packaging Maven/Gradle et tests unitaires JUnit