IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Contribuez Discussion :

[Image/Java] Analyse en composante principale / Axes principaux


Sujet :

Contribuez

  1. #1
    Modérateur
    Avatar de ToTo13
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Janvier 2006
    Messages
    5 793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 793
    Points : 9 860
    Points
    9 860
    Par défaut [Image/Java] Analyse en composante principale / Axes principaux
    Bonjour,

    voilà une petite contribution permettant de calculer une Analyse en Composante Principale (ACP ou PCA pour Principal Component Analysis) et l'axe principal d'inertie d'une forme.

    Pour ceux qui souhaitent :
    - la classe permettant de gérer des fichiers tabulés se trouve ici. Cela permet de travailler en dimension N avec un nombre de points/individus indéterminés.
    - la classe Jacobi est la même que celle du Numerical Recipse.
    - Jama est le package bien connu en Java pour la gestion des matrices.
    - Euclidian calcule simplement la distance Euclidienne.
    - Pour le reste, voir plus bas.
    - BaryBoiteContPeriSurf calcule => Barycentre, Boite englobante, Contour, Perimetre et Surface. Dans le cas de l'ACP, seul le barycentre est utile.



    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
     
    package rdf.pca;
     
    import Jama.Matrix;
     
    import filesAndFolders.fichiersTabules.FichierTabule;
     
    import imageTiTi.Image;
     
    import mathematics.Geometry;
    import mathematics.matriciel.Jacobi;
    import mathematics.matriciel.Vector;
    import mathematics.matriciel.Vectors;
    import mathematics.metrics.Euclidian;
    import mathematics.metrics.Metric;
    import mathematics.primitives.pointsTiTi.Point;
    import mathematics.primitives.pointsTiTi.PointND;
    import mathematics.statistics.CoVarianceMatrix;
    import mathematics.statistics.CorrelationMatrix;
     
    import measures.BaryBoiteContPeriSurf;
     
    import utils.chronometer.Chronometer;
     
    /**
     * <p>Description : Cette classe permet d'effectuer une analyse en composante principale.</p>
     * <p>Package necessaires : DV, filesAndFolders, imageTiTi, mathematics, measures, utils.</p>
     * <p>Dernieres modifications :<br>
     * 15 Aout 2009 (No Life ces thesards) => Creation.</p>
     * <p>Copyright : Copyright (c) 2007.</p>
     * <p>Laboratoire : LSIS.</p>
     * <p>Equipe : Image et Modele, I&M (ex LXAO).</p>
     * 
     * @author Guillaume THIBAULT
     * @version 1.0
     */
     
    public class PCA
    {
     
    protected CorrelationMatrix CoRe = null ;
    protected CoVarianceMatrix CoVa = null ;
    protected double[] EigenValues = null ;
    protected Vector[] EigenVectors = null ;
    protected Point Barycenter = null ;
    protected Jacobi jacobi = null ;
    protected Metric distances = new Euclidian() ;
     
     
     
    public PCA()
    	{
    	CoRe = new CorrelationMatrix() ;
    	CoVa = new CoVarianceMatrix() ;
    	jacobi = new Jacobi() ;
    	distances = new Euclidian() ;
    	}
     
     
    /** Methode qui effectue les calculs a partir d'un fichier tabule.
     * @param fichier Le fichier contenant les donnees. ATTENTION, toutes les colonnes valides sont traitees.
     * @param Reduce Doit on reduire la matrice (division par l'ecart type).
     * @param Chrono Le chronometre pour mesurer le temps d'execution.*/
    public void Compute(FichierTabule fichier, boolean Reduce, Chronometer Chrono)
    	{
    	int x, y ;
    	Matrix mat = null, vectors = null ;
     
    	if ( Chrono != null )
    		{
    		System.out.print("Principal component analysis: ") ;
    		Chrono.setMarqueur() ;
    		}
     
    	Barycenter = null ;
    	if ( Reduce )
    		{
    		mat = CoRe.Compute(fichier) ;
    		Barycenter = new PointND(CoRe.getAverages()) ;
    		}
    	else
    		{
    		mat = CoVa.Compute(fichier) ;
    		Barycenter = new PointND(CoVa.getAverages()) ;
    		}
     
    	int width = mat.getColumnDimension() ;
    	EigenValues = null ;
    	EigenValues = new double[width] ;
    	vectors = new Matrix(width, width) ;
     
    	jacobi.Compute(mat, EigenValues, vectors) ;
     
    	EigenVectors = new Vector[width] ; // On met les vecteurs résultats dans le tableau.
    	for (x=0 ; x < width ; x++)
    		{
    		EigenVectors[x] = new Vectors(mat.getRowDimension()) ;
    		for (y=0 ; y < mat.getRowDimension() ; y++)
    			EigenVectors[x].set(y, vectors.get(y, x)) ;
    		}
     
    	ComputeNewCoordinates(fichier) ;
     
    	mat = null ;
    	vectors = null ;
    	if ( Chrono != null ) System.out.println(Chrono.getTimeSinceMarqueurSecondes()) ;
    	}
     
     
     
     
    /** Methode qui permet de calculer les nouvelles coordonnees des points (contenus dans le fichier) dans le nouveau referentiel forme par les axes principaux.
     *  Ces axes sont construit a partir des vecteurs propres et l'origine est le barycentre des valeurs contenues dans le fichier ayant servi a faire les calculs. 
     * @param fichier Le fichier contenant les individus dont on souhaite trouver les nouvelles coordonnees dans le nouveau referentiel.
     * @return Le fichier contenant les nouvelles valeurs.*/ 
    public FichierTabule ComputeNewCoordinates(FichierTabule fichier)
    	{
    	if ( Barycenter == null ) throw new Error("Call method Compute before ComputeNewCoordinates.") ;
     
    	int x, y ;
    	int height = fichier.getHauteur() ;
    	int width = fichier.getLargeur() ;
    	int Size = EigenValues.length ;
    	Point P = new PointND(Size) ;
     
    	int[] Types = new int[Size] ;
    	for (x=y=0 ; x < Size ; x++) Types[x] = FichierTabule.DOUBLE ;
     
    	FichierTabule result = new FichierTabule(fichier.getHauteur(), Types) ;
     
    	for (x=y=0 ; x < width ; x++)
    		if ( !fichier.isExcludedColumn(x) ) y++ ;
    	if ( y != Size ) throw new IllegalArgumentException("Nombre de colonnes valides du fichier différent de celui du fichier ayant servi à faire les calculs.") ;
     
    	for (y=0 ; y < height ; y++)
    		if ( !fichier.isExcluded(y) ) // L'individu n'est pas exclu.
    			{
    			for (x=0 ; x < width ; x++) // On récupère les composantes de l'individu et on les place dans le point P.
    				if ( !fichier.isExcludedColumn(x) )
    					switch ( fichier.getTypeColonne(x) )
    						{
    						case FichierTabule.INTEGER : P.set(x, fichier.getValueInt(y, x)) ; break ;
    						case FichierTabule.DOUBLE : P.set(x, fichier.getValueDouble(y, x)) ; break ;
    						default : throw new IllegalArgumentException("Only Integer or Double column type required.") ;
    						}
     
    			for (x=0 ; x < Size ; x++) // On calcule les coordonnées de P => projection sur les axes représentés par les vecteurs propres, origine=barycenter.
    				result.setValue(y, x, Geometry.IntersectionCoef(Barycenter, EigenVectors[x], P)) ;
    			}
     
    	Types = null ;
    	P = null ;
    	return result ;
    	}
     
     
     
     
     
     
    /** Methode qui effectue les calculs a partir d'une image.
     * @param image L'image sur laquelle on souhaite effectuer l'ACP.
     * @param Chrono Le chronometre pour mesurer le temps d'execution.*/
    public void Compute(Image image, Chronometer Chrono)
    	{
    	BaryBoiteContPeriSurf Bbcps = new BaryBoiteContPeriSurf() ;
    	Bbcps.Compute(image, true, Chrono) ;
    	Compute(image, Bbcps.Centroid, Chrono) ;
    	}
     
     
    /** Methode qui effectue les calculs a partir d'une image.
     * @param image L'image sur laquelle on souhaite effectuer l'ACP.
     * @param Centroid Le barycentre.
     * @param Chrono Le chronometre pour mesurer le temps d'execution.*/
    public void Compute(Image image, Point Centroid, Chronometer Chrono)
    	{
    	if ( image == null ) throw new Error("image == null.") ;
     
    	int x, y, width ;
    	int largeur = image.getWidth() ;
    	int hauteur = image.getHeight() ;
    	double MomIneX, MomIneY, MomIneXY ;
    	double Bx, By ;
    	Matrix mat = null, vectors = null ;
     
    	if ( Chrono != null )
    		{
    		System.out.print("Calcul des axes principaux d'inertie : ") ;
    		Chrono.setMarqueur() ;
    		}
     
    	this.Barycenter = null ;
    	this.Barycenter = Centroid.Clone() ;
    	Bx = Centroid.getX() ;
    	By = Centroid.getY() ;
     
    	MomIneX = MomIneY = MomIneXY = 0.0 ;
    	for (y=0 ; y < hauteur ; y++)
    		for (x=0 ; x < largeur ; x++)
    			if ( image.Pixel(y, x) > 0 )
    				{
    				MomIneX += Math.pow((double)x-Bx, 2.0) ;
    				MomIneY += Math.pow((double)y-By, 2.0) ;
    				MomIneXY += ((double)x-Bx) * ((double)y-By) ;
    				}	
     
    	mat = new Matrix(new double[][]{{MomIneX, MomIneXY}, {MomIneXY, MomIneY}}) ;
    	width = mat.getColumnDimension() ;
    	EigenValues = null ;
    	EigenValues = new double[width] ;
    	vectors = new Matrix(width, width) ;
     
    	jacobi.Compute(mat, EigenValues, vectors) ;
     
    	EigenVectors = new Vector[width] ; // On met les vecteurs résultats dans le tableau.
    	for (x=0 ; x < width ; x++)
    		{
    		EigenVectors[x] = new Vectors(mat.getRowDimension()) ;
    		for (y=0 ; y < mat.getRowDimension() ; y++)
    			EigenVectors[x].set(y, vectors.get(y, x)) ;
    		}
     
    	vectors = null ;
    	mat = null ;
    	if ( Chrono != null ) System.out.println(Chrono.getTimeSinceMarqueurSecondes()) ;
    	}
     
     
     
     
     
     
    public CorrelationMatrix getCorelationMatrix()
    	{
    	return CoRe ;
    	}
     
    public CoVarianceMatrix getCovarianceMatrix()
    	{
    	return CoVa ;
    	}
     
    public double[] getEigenValues()
    	{
    	return EigenValues ;
    	}
     
    public Vector[] getEigenVectors()
    	{
    	return EigenVectors ;
    	}
     
    public Point getBarycenter()
    	{
    	return Barycenter ;
    	}
     
    }
    Consignes aux jeunes padawans : une image vaut 1000 mots !
    - Dans ton message respecter tu dois : les règles de rédaction et du forum, prévisualiser, relire et corriger TOUTES les FAUTES (frappes, sms, d'aurteaugrafe, mettre les ACCENTS et les BALISES) => ECRIRE clairement et en Français tu DOIS.
    - Le côté obscur je sens dans le MP => Tous tes MPs je détruirai et la réponse tu n'auras si en privé tu veux que je t'enseigne.(Lis donc ceci)
    - ton poste tu dois marquer quand la bonne réponse tu as obtenu.

  2. #2
    Modérateur
    Avatar de ToTo13
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Janvier 2006
    Messages
    5 793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 793
    Points : 9 860
    Points
    9 860
    Par défaut Axe principal d'une forme binaire par ACP
    Voici un petit exemple de l'utilisation du code ci-dessus :
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    PCA pca = new PCA() ;
    pca.Compute(image, Centroid, Chrono) ; // Centroid est un point : le barycentre de la forme.
    // L'axe principal est alors défini par un point et un vecteur, car cela permet d'avoir la même représentation dans TOUTES les dimensions.
    Point B = pca.getBarycenter() ; // Le barycentre de la forme qui est en fait égal a Centroid.
    Vectot V = pca.getEigenVectors()[0] ; // L'axe principal est le premier vecteur du tableau. Ce tableau étant classé de manière décroissante en fonction des valeurs propres calculées lors de la diagonalisation.




    La méthode utilisée dans la Classe Geometry :
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    /** Methode qui calcule la projection orthogonale du point P sur une droite D representee par un point X et un vecteur V (P = X + kV).
     *  ATTENTION : cette methode renvoit le coefficient k.  
     * @param X Un point de la droite D.
     * @param V Le vecteur directeur de la droite D.
     * @param P Le point dont on souhaite connaitre le projete sur la droite D.
     * @return Le coefficient de k de P = X + kV.*/
    public static double IntersectionCoef(Point X, Vector V, Point P)
    	{
    	if ( X.Size() != P.Size() || P.Size() != V.Dimension() ) throw new IllegalArgumentException("Gap dimensions between parameters.") ;
     
    	int Size = V.Dimension() ;
    	double num = 0.0, den = 0.0 ;
     
    	for (int i=0 ; i < Size ; i++)
    		{
    		num += V.get(i) * (P.get(i)-X.get(i)) ;
    		den += Math.pow(V.get(i), 2.0) ;
    		}
     
    	if ( Math.abs(den) < Epsilon ) throw new ArithmeticException("Denominator equal to zero => Vector V is a vector null.") ;
    	return num / den ;
    	}
    Consignes aux jeunes padawans : une image vaut 1000 mots !
    - Dans ton message respecter tu dois : les règles de rédaction et du forum, prévisualiser, relire et corriger TOUTES les FAUTES (frappes, sms, d'aurteaugrafe, mettre les ACCENTS et les BALISES) => ECRIRE clairement et en Français tu DOIS.
    - Le côté obscur je sens dans le MP => Tous tes MPs je détruirai et la réponse tu n'auras si en privé tu veux que je t'enseigne.(Lis donc ceci)
    - ton poste tu dois marquer quand la bonne réponse tu as obtenu.

Discussions similaires

  1. Analyse en composantes principales en Java
    Par jmini dans le forum Langage
    Réponses: 4
    Dernier message: 01/12/2014, 18h03
  2. Réponses: 5
    Dernier message: 27/01/2012, 16h31
  3. [Débutante] Analyse en composantes principales
    Par cixidetroy dans le forum MATLAB
    Réponses: 3
    Dernier message: 16/06/2008, 15h33
  4. Analyse en composantes principales
    Par afnane dans le forum Méthodes exploratoires
    Réponses: 1
    Dernier message: 12/06/2008, 16h25
  5. Analyse en composante principale
    Par progfou dans le forum Algorithmes et structures de données
    Réponses: 2
    Dernier message: 22/03/2007, 14h26

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo